java反射是di容器核心,支撑类扫描、注解识别、元信息提取及实例化装配全过程,实现运行时动态管理bean生命周期。

Java 反射是实现依赖注入(DI)容器核心逻辑的底层能力,它让容器能在运行时“看见”类结构、读取注解、创建实例并装配依赖,而不依赖编译期硬编码。
扫描包路径并加载候选类
容器启动时需定位哪些类属于可管理组件(如标注 @Component 的类):
- 用 ClassLoader.getResources("com/example/service/") 获取包路径对应资源 URL(可能是文件目录或 jar 内路径)
- 对每个 URL 解析为 File 或遍历 JarEntry,筛选出以 .class 结尾的条目
- 从文件名反推全限定类名(如 UserService.class → com.example.service.UserService),再调用 Class.forName() 加载
- 需兼容不同环境:IDE 运行时路径是 file://,打包后可能是 jar:file:///xxx.jar!/com/example/
通过反射识别与过滤 Bean 候选者
加载类后不立即实例化,而是先判断是否符合注入条件:
- 调用 clazz.isAnnotationPresent(Component.class) 检查核心注解;@Service、@Repository 因元注解了 @Component,也能被命中
- 跳过接口(clazz.isInterface())、抽象类(clazz.isInterface() || clazz.getModifiers() & Modifier.ABSTRACT != 0)、合成类(clazz.isSynthetic())和匿名内部类
- 支持扩展:只需在判断逻辑中加入对自定义注解(如 @MyBean)的 isAnnotationPresent 检查
提取元信息并准备注入上下文
确认为候选 Bean 后,用反射提前采集结构信息,为后续实例化与赋值铺路:
- 生成 Bean 名称:默认取类名首字母小写(UserServiceImpl → userServiceImpl),而非简单 toLowerCase()(避免 XMLParser → xMLParser)
- 获取构造器:clazz.getDeclaredConstructors(),优先找无参构造;若需有参,则按参数类型递归查找已注册 Bean
- 获取字段:clazz.getDeclaredFields(),遍历检查是否标注 @Autowired 或自定义注入注解
- 对每个匹配字段缓存其类型(field.getType())、名称(field.getName()),并调用 field.setAccessible(true) 突破 private 访问限制
实例化与依赖装配的关键操作
真正创建对象并完成注入时,反射承担核心调度角色:
- 调用 constructor.newInstance(args) 实例化对象;若构造器含参数,args 由容器中已有的 Bean 类型匹配填充
- 对每个带注入注解的字段,从容器中查出对应类型实例(支持 byType 或 byName,如 @Autowired(value = "emailService"))
- 执行 field.set(instance, bean) 完成赋值;注意处理 null 注入基本类型字段会抛异常,应只对包装类或对象类型操作
- 循环依赖防护:在 new 出实例后、注入前,先放入“正在创建中”缓存;后续依赖该类时直接返回此半成品对象,避免无限递归
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











