Java可通过反射+注解手动实现轻量级DI容器:先定义@Component标记Bean类、@Autowired标记注入点;再扫描类、递归实例化并注入依赖,用Map缓存单例对象。

Java 中可以通过反射 + 注解,手动实现一个轻量级依赖注入容器,核心思路是:扫描类、识别带注解的字段/构造器、递归创建并注入依赖对象。
定义注入相关的注解
先自定义两个常用注解,模拟 Spring 的 @Component 和 @Autowired:
- @Component:标记可被容器管理的 Bean 类(如服务类、仓库类)
- @Autowired:标记需要自动注入的字段或构造器参数
示例:
```java@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component { }
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired { }
```
构建简易 IOC 容器
容器需完成三件事:收集所有 @Component 类、实例化它们、按 @Autowired 注入依赖。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
Map<class>, Object></class>缓存已创建的单例 Bean - 扫描指定包路径下所有 class 文件,用
Class.forName()加载类,检查是否含@Component - 对每个匹配类,调用无参构造器创建实例;若构造器有
@Autowired,则解析参数类型并从容器中获取对应 Bean - 字段注入时,设
field.setAccessible(true)突破 private 限制,再用field.set(instance, bean)
处理循环依赖(基础版)
简单场景下可借助“提前暴露半成品对象”策略:
- 在 new 实例后、注入前,先把空对象 put 到缓存中
- 后续注入时若发现依赖尚未完全初始化,就取这个半成品对象(只要不调用未初始化的方法即可)
- 注意:此方式仅支持构造器注入或字段注入中的一类,且不支持复杂代理场景
使用示例
假设有 UserDao、UserService 两层依赖:
@Component
public class UserDao { }
@Component
public class UserService {
@Autowired private UserDao userDao;
// 构造器也可加 @Autowired(优先级高于字段)
}
启动时调用 MyApplicationContext.refresh("com.example") 扫描包,之后可通过 context.getBean(UserService.class) 获取已注入依赖的实例。
不复杂但容易忽略细节:类加载路径、泛型擦除导致的类型匹配问题、多实现类时的歧义处理——这些进阶点可在基础版跑通后再扩展。

















