要實(shí)現(xiàn)的功能:
- 將對(duì)象的實(shí)例化交給自定的ioc容器.
- 通過注解的方式對(duì)接口進(jìn)行依賴注入
- 通過getBean("userName")方法那到對(duì)象,使用對(duì)象的方法
-
首先,創(chuàng)建一個(gè)對(duì)象,定義對(duì)象的構(gòu)造函數(shù)
package cn.lisongyu.ioc.demo.bean; import cn.lisongyu.ioc.annotation.Component; /** * @author lisongyu * @ClassName cn.lisongyu.ioc.demo.bean.UserBean * @description userbean * @create 2018年11月22日 11:08 */ @Component //自定義的組件,讓ioc容器掃描帶有指定注解的類,將當(dāng)前類裝配到ioc容器中 public class UserBean { @Autowired //自定義的注入注解 private Service service; public UserBean() { System.out.println("UserBean -> instance"); } public void getUser(){ service.test(); //接口的方法,如果注入失敗,將報(bào)空指針異常 System.out.println("用戶詳情展示"); } }
package cn.lisongyu.ioc.demo.a.b.c; import cn.lisongyu.ioc.annotation.Component; import cn.lisongyu.ioc.demo.a.b.Service; /** * @author lisongyu * @ClassName cn.lisongyu.ioc.demo.a.b.c.TestService * @description Service實(shí)現(xiàn)類 * @create 2018年11月22日 11:22 */ @Component public class TestService implements Service { public TestService() { System.out.println("TestService -> instance"); } @Override public void test() { System.out.println("Service 接口實(shí)現(xiàn)方法"); } }
package cn.lisongyu.ioc.demo.a.b; /** * /** * * @author lisongyu * @ClassName cn.lisongyu.ioc.demo.a.b.Service * @description Service接口 * @create 2018年11月22日 17:31 */ public interface Service { void test(); }
-
創(chuàng)建自定義的注解
package cn.lisongyu.ioc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //依賴注入注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) //只能注解到字段上 public @interface Autowired { }
package cn.lisongyu.ioc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //組件注解 @Retention(RetentionPolicy.RUNTIME) //程序運(yùn)行時(shí)執(zhí)行 @Target(ElementType.TYPE) //該注解指定標(biāo)注的位置 TYPE:類 public @interface Component { }
-
定義一個(gè)接口,用來獲取bean對(duì)象的方法
package cn.lisongyu.ioc.context; /** * /** * Application 接口 * @author lisongyu * @ClassName cn.lisongyu.ioc.context.Application * @description * @create 2018年11月22日 11:24 */ public interface Application { Object getBean(String beanName); }
package cn.lisongyu.ioc.context; import cn.lisongyu.ioc.annotation.Component; import java.io.File; import java.io.FileFilter; import java.net.URL; import java.sql.SQLOutput; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.concurrent.ConcurrentHashMap; /** * @author lisongyu * @ClassName cn.lisongyu.ioc.context.ApplicationImpl * @description Application的實(shí)現(xiàn)類 * @create 2018年11月22日 11:24 */ public class ApplicationImpl implements Application { //定義存放所有類對(duì)象的集合 private List<Class<?>> classList = new ArrayList<>(); //定義存放類的實(shí)例對(duì)象的集合 private Map<String,Object> instanceMap = new ConcurrentHashMap<>(); //無參構(gòu)造 public ApplicationImpl() { } /** * 有參構(gòu)造,通過傳入的包路徑來實(shí)現(xiàn)掃描 * @param basePackage */ public ApplicationImpl(String basePackage) { //掃描包路徑 doScan(basePackage); //實(shí)例化 doIoc(); System.out.println(instanceMap); //依賴注入 doDi(); } /** * 實(shí)例化對(duì)象 */ private void doIoc() { //首先判斷一下當(dāng)前類集合中是否含有元素 if (classList == null){ return; } //遍歷集合 classList.forEach((clz) ->{ try { //通過類對(duì)象,實(shí)例化一個(gè)對(duì)象 Object instance = clz.newInstance(); //創(chuàng)建key String key = getKeyName(clz.getSimpleName()); //存放到map集合中 //如果集合中存在則報(bào)錯(cuò) if (instanceMap.containsKey(key)){ throw new RuntimeException("相同的類名"); } //放入ioc容器中 instanceMap.put(key,instance); //判斷當(dāng)前類是否實(shí)現(xiàn)了接口 Class<?>[] interfaces = clz.getInterfaces(); for (Class<?> inter : interfaces) { instanceMap.put(inter.getName(),instance); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }); } //改名,獲取一個(gè)首字母小寫的類名 private String getKeyName(String simpleName) { char[] chars = simpleName.toCharArray(); chars[0] += 32; return String.valueOf(chars); } //依賴注入 private void doDi() { //首先判斷實(shí)例對(duì)象是否有 if (instanceMap.size() == 0) return; //遍歷所有的實(shí)例對(duì)象 instanceMap.forEach((k,v) -> { Object instance = v; //注入實(shí)體對(duì)象 Object injectionInstance = null; //通過反射獲取類對(duì)象 Class<?> clz = v.getClass(); //獲取當(dāng)前類對(duì)象的所有聲明的字段 Field[] fields = clz.getDeclaredFields(); //循環(huán)遍歷所有字段 for (Field field : fields) { //判斷字段是否含有@Autowired注解 if(field.isAnnotationPresent(Autowired.class)){ String name = field.getType().getName(); injectionInstance = this.instanceMap.get(name); } // 通過反射注入到該屬性中 field.setAccessible(true); try { field.set(instance,injectionInstance); } catch (IllegalAccessException e) { e.printStackTrace(); } } }); } //包掃描方法 private void doScan(String basePackage) { //獲取當(dāng)前包的位置 URL resource = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/")); //創(chuàng)建一個(gè)文件對(duì)象 File file = new File(resource.getPath()); //遍歷文件 File[] fileNames = file.listFiles(new FileFilter() { @Override public boolean accept(File childFile) { //判斷當(dāng)前文件是否是一個(gè)文件夾 if (childFile.isDirectory()){ //如果是文件夾,遞歸,獲取所有的class文件 doScan(basePackage+"."+childFile.getName()); }else { //判斷當(dāng)前文件是否是一個(gè)類文件 if (childFile.getName().endsWith(".class")){ String classPath = basePackage + "." + childFile.getName().replaceAll("\\.class", ""); Class<?> clz = null; try { clz = Class.forName(classPath); //判斷是否是有@Component注解的類 if (clz.isAnnotationPresent(Component.class)){ classList.add(clz); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } return false; } }); } @Override public Object getBean(String beanName) { return this.instanceMap.get(beanName); } }
-
運(yùn)行main()
package cn.lisongyu.ioc; import cn.lisongyu.ioc.context.Application; import cn.lisongyu.ioc.context.ApplicationImpl; import cn.lisongyu.ioc.demo.bean.UserBean; import java.util.*; /** * Hello world! * */ public class App { public static void main( String[] args ) { //包路徑 Application app = new ApplicationImpl("cn.lisongyu.ioc.demo"); UserBean userBean = (UserBean) app.getBean("userBean"); userBean.getUser(); } }
-
結(jié)果:
TestService -> instance //接口實(shí)現(xiàn)類的初始化 UserBean -> instance //對(duì)象類的初始化 {cn.lisongyu.ioc.demo.a.b.Service=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, testService=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, userBean=cn.lisongyu.ioc.demo.bean.UserBean@6d03e736} //裝配到容器中的類 Service 接口實(shí)現(xiàn)方法 //service.test(); 用戶詳情展示 //userBean.getUser();
?