504. Java 反射 - 创建一个简单的依赖注入框架

📅 2026/8/25 6:31:23
504. Java 反射 - 创建一个简单的依赖注入框架
文章目录504. Java 反射 - 创建一个简单的依赖注入框架1. 什么是依赖注入DI2. 我们的目标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)publicinterfaceSingleton{}Target(ElementType.FIELD)Retention(RetentionPolicy.RUNTIME)publicinterfaceInject{}4. 编写依赖工厂DI 容器DependencyFactory负责检查类上是否有Singleton注解如果有则复用同一个实例。使用反射扫描字段找到Inject注解并创建/注入依赖对象。publicclassDependencyFactory{privatestaticfinalMapClass?,ObjectsingletonsnewHashMap();publicstaticTTgetInstance(ClassTclazz){try{// ✅ 单例处理if(clazz.isAnnotationPresent(Singleton.class)){if(singletons.containsKey(clazz)){return(T)singletons.get(clazz);}}// ✅ 通过无参构造器创建对象Tinstanceclazz.getConstructor().newInstance();// ✅ 依赖注入for(Fieldfield:clazz.getDeclaredFields()){if(field.isAnnotationPresent(Inject.class)){field.setAccessible(true);ObjectdependencygetInstance(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(){returnUser[Tom];}}publicclassUserService{InjectprivateUserRepositoryrepository;publicvoidprocessUser(){System.out.println(Processing: repository.getUser());}}6. 测试依赖注入publicclassMain{publicstaticvoidmain(String[]args){UserServiceserviceDependencyFactory.getInstance(UserService.class);service.processUser();}}输出Processing:User[Tom]这里UserService并没有自己 newUserRepository而是通过框架自动注入得到的实例。7. 总结对比现实框架Spring 的Autowired、Jakarta EE 的Inject就是类似机制。DI 的好处降低耦合、集中管理依赖、便于扩展。局限性我们这里的框架比较简化不支持作用域、懒加载、构造函数注入等高级特性。