前言
依赖反转(IoC)是Spring中一个非常重要的功能。我们基于java反射机制,来尝试实现一个简单的IoC。
原文地址:https://xuedongyun.cn/post/35893/
回顾反射
获取Class对象
- 类名.class
1
| Class clazz = Car.class;
|
- 对象.getClass
1 2
| Car car = new Car(); Class clazz = car.getClass();
|
- Class.forName + 全类名
1
| Class clazz = Class.forName("com.xuedongyun.project.Car");
|
获取构造方法
- 获取所有构造方法
1 2 3 4 5
| Constructor[] constructors = clazz.getConstructors();
Constructor[] constructors = clazz.getDeclaredConstructors();
|
- 指定获取有参构造器
1 2 3 4 5 6 7 8
| Constructor c = clazz.getConstructor(String.class, int.class, String.class);
Constructor c = clazz.getConstructor();
Constructor c = clazz.getDeclaredConstructor(String.class, int.class, String.class);
|
- 创建对象
1 2 3
| constructor.setAccessible(true); Car car = constructor.newInstance();
|
获取属性
- 获取所有属性
1 2 3 4 5
| Field[] fields = clazz.getFields();
Field[] fields = clazz.getDeclaredFields();
|
- 获取某个属性
1 2 3 4 5
| Field field = clazz.getField("name");
Field field = clazz.getDeclaredField("name");
|
- 修改属性
1 2 3
| field.setAccessible(true); field.set(car,"五菱宏光");
|
获取方法
- 获取所有方法
1 2 3 4 5
| Method[] methods = clazz.getMethods();
Method[] methods = clazz.getDeclaredMethods();
|
- 获得某一个方法
1 2 3 4 5
| Method m = clazz.getMethod("func", String.class, int.class);
Method m = clazz.getDeclaredMethod("func", String.class, int.class);
|
- 执行方法
1 2 3
| m.setAccessible(true); Object result = m.invoke(car, "test", 123);
|
int.class表示基本数据类型int的Class对象,以便在反射时使用。它等价于Integer.TYPE
实现Spring的IoC
创建所需的注解
Bean注解
1 2 3 4 5 6
| package org.example.annotation;
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Bean { }
|
依赖注入的注解
1 2 3 4 5 6
| package org.example.annotation;
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Autowired { }
|
定义IoC容器
定义容器接口
1 2 3 4 5
| package org.example.context;
public interface ApplicationContext { Object getBean(Class<?> clazz); }
|
定义容器实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package org.example.context;
public class AnnotationApplicationContext implements ApplicationContext{ private Map<Class<?>, Object> beanFactory = new HashMap<>();
public AnnotationApplicationContext(String basePackage) { }
@Override public Object getBean(Class<?> clazz) { return beanFactory.get(clazz); } }
|
扫描Bean功能
获取packageDirName
的绝对路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public AnnotationApplicationContext(String basePackage) { String packageDirName = basePackage.replace(".", "\\"); try { Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); while (dirs.hasMoreElements()) { URL url = dirs.nextElement(); String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8); String rootPath = filePath.substring(0, filePath.length() - packageDirName.length()); loadBean(new File(rootPath)); } } catch (IOException e) { throw new RuntimeException(e); } }
|
遍历所有.class文件,若标注有@Bean
注解,则将其实例化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public void loadBean(File fileParent, String rootPath) { if (fileParent.isDirectory()) { File[] childFiles = fileParent.listFiles(); if (childFiles == null || childFiles.length == 0) { return; } for (File childFile : childFiles) { if (childFile.isDirectory()) { loadBean(childFile, rootPath); continue; } String pathWithClass = childFile.getAbsolutePath().substring(rootPath.length() - 1); if (!pathWithClass.contains(".class")) { continue; } try { String fullName = pathWithClass.replace("\\", ".").replace(".class", ""); Class<?> clazz = Class.forName(fullName); if (clazz.isAnnotation() || clazz.isInterface()) { continue; } Bean annotation = clazz.getAnnotation(Bean.class); if (annotation != null) { Object instance = clazz.getConstructor().newInstance(); if (clazz.getInterfaces().length > 0) { beanFactory.put(clazz.getInterfaces()[0], instance); } else { beanFactory.put(clazz, instance); } } } catch (Exception e) { throw new RuntimeException(e); } } } }
|
依赖注入
1 2 3 4 5 6
| public AnnotationApplicationContext(String basePackage) { loadDi(); }
|
实现依赖注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public void loadDi() { for (Map.Entry<Class<?>, Object> entry : beanFactory.entrySet()) { Object obj = entry.getValue(); Class<?> clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { Autowired annotation = field.getAnnotation(Autowired.class); if (annotation != null) { field.setAccessible(true); try { field.set(obj, beanFactory.get(field.getType())); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } } }
|
使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| package org.example.test;
@Bean public class Pet { private String name = "dodo";
@Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package org.example.test;
@Bean public class User {
@Autowired private Pet pet;
private String name = "xdy";
@Override public String toString() { return "User{" + "pet=" + pet + ", name='" + name + '\'' + '}'; } }
|
1 2 3 4 5 6 7 8 9
| package org.example;
public class Main { public static void main(String[] args) { ApplicationContext context = new AnnotationApplicationContext("org.example"); Object bean = context.getBean(User.class); System.out.println("bean = " + bean); } }
|