1、定义IOC容器接口
public interface ApplicationContext { public Object getBean(Class clazz); }
2、实现IOC接口
public class AnnotationApplicationContext implements ApplicationContext{ private Map<Class,Object> beanFactory = new HashMap<>(); private static String rootPath; public AnnotationApplicationContext (String basePackage){ try { String packagePath = basePackage.replaceAll("\\.", "\\\\"); Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(packagePath); while (resources.hasMoreElements()){ URL url = resources.nextElement(); String filePath = URLDecoder.decode(url.getFile(), "utf-8"); rootPath = filePath.substring(0,filePath.length()-packagePath.length()); loadBean(new File(filePath)); } } catch (IOException e) { e.printStackTrace(); } loadDI(); } public Object getBean(Class clazz) { return beanFactory.get(clazz); } private void loadBean(File file) { if (file.isDirectory()) { File[] childrenFiles = file.listFiles(); if(childrenFiles == null || childrenFiles.length == 0){ return; } for (File child : childrenFiles) { if (child.isDirectory()) { //如果是个文件夹就继续调用该方法,使用了递归 loadBean(child); } else { //通过文件路径转变成全类名,第一步把绝对路径部分去掉 String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1); //选中class文件 if (pathWithClass.contains(".class")) { // com.xinzhi.dao.UserDao //去掉.class后缀,并且把 \ 替换成 . String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", ""); try { Class<?> aClass = Class.forName(fullName); //把非接口的类实例化放在map中 if(!aClass.isInterface()){ Bean annotation = aClass.getAnnotation(Bean.class); if(annotation != null){ Object instance = aClass.getConstructor().newInstance(); //判断一下有没有接口 if(aClass.getInterfaces().length > 0) { //如果有接口把接口的class当成key,实例对象当成value System.out.println("正在加载【"+ aClass.getInterfaces()[0] +"】,实例对象是:" + instance.getClass().getName()); beanFactory.put(aClass.getInterfaces()[0], instance); }else{ //如果有接口把自己的class当成key,实例对象当成value System.out.println("正在加载【"+ aClass.getName() +"】,实例对象是:" + instance.getClass().getName()); beanFactory.put(aClass, instance); } } } } catch (Exception e) { e.printStackTrace(); } } } } } } private void loadDI() { for(Map.Entry<Class,Object> entry : beanFactory.entrySet()){ //放在容器的对象 Object obj = entry.getValue(); Class<?> aClass = obj.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); for (Field field : declaredFields){ DI annotation = field.getAnnotation(DI.class); if( annotation != null ){ field.setAccessible(true); try { System.out.println("正在给【"+obj.getClass().getName()+"】属性【" + field.getName() + "】注入值【"+ beanFactory.get(field.getType()).getClass().getName() +"】"); field.set(obj,beanFactory.get(field.getType())); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } } }
3、定义注解@Bean和@DI
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Bean { }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DI { }
4、定义并实现DAO接口
public interface UserDAO { void add(); }
@Bean public class UserDAOImpl implements UserDAO { @Override public void add() { System.out.println("DAO add ..."); } }
5、定义并实现Service接口
public interface UserService { void addUser(); }
@Bean public class UserServiceImpl implements UserService { @DI private UserDAO userDAO; @Override public void addUser() { System.out.println("service...."); userDAO.add(); } }
6、创建Controller层
@Bean public class UserController { @DI private UserService userService; public void add(){ System.out.println("controller..."); userService.addUser(); } }
7、测试IOC容器
ApplicationContext context = new AnnotationApplicationContext("com.jixian"); UserController userController = (UserController) context.getBean(UserController.class); userController.add();
8、总结
IOC的实现通过反射加注解,进行包扫描检查类上的注解,如果有@Bean注解就通过反射创建对象,并把对象放在Map中,遍历Map集合检查属性上是否含有@DI注解,将含有@DI注解的属性通过反射进行赋值。
标签:aClass,DI,class,field,Bean,手写,IOC,public From: https://www.cnblogs.com/jixian/p/17159064.html