504. Java 反射 - 创建一个简单的依赖注入框架
文章目录
- 504. Java 反射 - 创建一个简单的依赖注入框架
- 1. 什么是依赖注入(DI)?
- 2. 我们的目标
- 3. 定义注解
- 4. 编写依赖工厂(DI 容器)
- 5. 编写业务类示例
- 6. 测试依赖注入
- 输出:
- 7. 总结
504. Java 反射 - 创建一个简单的依赖注入框架
1. 什么是依赖注入(DI)?
依赖注入(Dependency Injection,简称DI)是一种设计模式,它的核心思想是:
👉不要自己手动创建对象,而是让“工厂/框架”来为你准备好依赖对象并注入到业务类中。
这样做的好处:
- 解耦:业务类不再依赖具体实现,只依赖抽象。
- 易于测试:可以轻松替换依赖(比如替换成 Mock 实现)。
- 生命周期管理:框架可以统一管理对象的创建、销毁、单例复用等。
很多企业级框架(如Spring、Jakarta EE、Guice)都是基于这种机制构建的。
2. 我们的目标
我们要写一个简化版的 DI 框架,支持两个功能:
- 单例模式 (Singleton):某些类只需要一个全局共享实例。
- 自动注入 (Injection):框架能自动扫描并填充需要的依赖字段。
3. 定义注解
我们先定义两个注解:
@Singleton:表示该类只能有一个实例。@Inject:表示该字段需要由框架来注入依赖。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public@interfaceSingleton{}@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public@interfaceInject{}4. 编写依赖工厂(DI 容器)
DependencyFactory负责:
- 检查类上是否有
@Singleton注解,如果有则复用同一个实例。 - 使用反射扫描字段,找到
@Inject注解,并创建/注入依赖对象。
publicclassDependencyFactory{privatestaticfinalMap<Class<?>,Object>singletons=newHashMap<>();publicstatic<T>TgetInstance(Class<T>clazz){try{// ✅ 单例处理if(clazz.isAnnotationPresent(Singleton.class)){if(singletons.containsKey(clazz)){return(T)singletons.get(clazz);}}// ✅ 通过无参构造器创建对象Tinstance=clazz.getConstructor().newInstance();// ✅ 依赖注入for(Fieldfield:clazz.getDeclaredFields()){if(field.isAnnotationPresent(Inject.class)){field.setAccessible(true);Objectdependency=getInstance(field.getType());// 递归创建field.set(instance,dependency);}}// ✅ 保存单例if(clazz.isAnnotationPresent(Singleton.class)){singletons.put(clazz,instance);}returninstance;}catch(Exceptione){thrownewRuntimeException("Failed to create instance for "+clazz,e);}}}5. 编写业务类示例
@SingletonpublicclassUserRepository{publicStringgetUser(){return"User[Tom]";}}publicclassUserService{@InjectprivateUserRepositoryrepository;publicvoidprocessUser(){System.out.println("Processing: "+repository.getUser());}}6. 测试依赖注入
publicclassMain{publicstaticvoidmain(String[]args){UserServiceservice=DependencyFactory.getInstance(UserService.class);service.processUser();}}输出:
Processing:User[Tom]这里UserService并没有自己 newUserRepository,而是通过框架自动注入得到的实例。
7. 总结
- 对比现实框架:Spring 的
@Autowired、Jakarta EE 的@Inject就是类似机制。 - DI 的好处:降低耦合、集中管理依赖、便于扩展。
- 局限性:我们这里的框架比较简化,不支持作用域、懒加载、构造函数注入等高级特性。
