有一个类 B ,里面依赖注入了 C
java
class B {
@Autowired C c;
}
Spring 会创建 B 的 Bean
- 这个 Bean 是完整的
- 已经完成了依赖注入
- 里面的
c是有值的 - 它是一个真正能正常工作的对象
- 现在要对 B 做 AOP,用 CGLIB 生成代理类 A
java
class A extends B {
// 代理类
}
-
重点来了:A 继承的是 B 这个类,不是继承 B 那个已经注入好的 Bean!
- 代理对象 A 自己是另外 new 出来的一个对象
- Spring 不会再给 A 做一遍依赖注入
- 所以 A 里面继承过来的
c字段 是 null
-
这就是为什么:在代理类 A 里面直接用
this.c、super.c都会空。因为代理对象自己根本没被注入。 -
所以 Spring 必须这么做:
- 先拿到那个完整、注入好的 B 的 Bean(叫 target)
- 让代理 A 持有这个 target 对象
- 代理不自己执行方法
- 真正调用时,用
target.method()去执行
-
最终效果:
- target 是完整 Bean,依赖都在
- 调用它的方法,
c有值,不会空指针 - 代理只负责增强(事务、日志等),不负责执行业务
最精简一句话总结
B 类的 Bean 是完整的、注入好的; 代理 A 只是继承了 B 类,自己没被注入,所以字段为空; 所以必须拿着原来那个 B 的 Bean 去调用方法,才能正常运行