spring中autowired注入自己的代理后,最后容器中的对象是原对象还是代理对象
问题场景假设类UserRightService中存在加了事务注解的方法,且通过@Autowired注入自身@Servicepublic class UserRightService {@Autowiredprivate UserRightService userRightService;@Transactionalpublic boolean checkUserFuncRight(String u
问题场景
假设类UserRightService中存在加了事务注解的方法,且通过@Autowired注入自身
@Service
public class UserRightService {
@Autowired
private UserRightService userRightService;
@Transactional
public boolean checkUserFuncRight(String userId, String url) {
......
......
}
}
根据spring启动原理:
1.当实例化
UserRightService类时,首先会注入自身UserRightService成员。由于类中存在加了事务注解的方法,于是最终注入的UserRightService成员是通过事务切面生产的代理对象。2.但此时仅仅是给自身生成员变量赋值,外层
UserRightService类实例化过程还未结束。
那么,由此引发了疑问:
最终实例化完成后,容器中的
UserRightService对象,是原对象,还是代理对象呢?
源码剖析
结合spring实例化UserRightService类的流程,我们一步步分析
1.通过构造方法创建UserRightService类
略
2.将函数式接口加入三级缓存
spring在完成对象的实例化之前,都会将对象代表的函数式接口放入自身的三级缓存(函数式接口的逻辑见第3步),三级缓存本质就是一个map结构。
3.通过populateBean方法注入成员变量UserRightService
有了对象之后,spring开始给对对象自身的成员变量赋值,方法如下
该方法会触发成员变量UserRightService的实例化。在实例化过程中,因为之前往三级缓存中放入了相关信息,所以此时调用到函数式接口的逻辑
在循环里,调用到AbstractAutoProxyCreator类的getEarlyBeanReference方法
方法里先往map类型的earlyProxyReferences成员变量中保存了UserRightService信息,然后通过wrapIfNecessary方法生成了UserRightService的代理对象。
此时,从三级缓存里就获得了通过事务切面生成的代理对象,并给UserRightService成员变量赋值,同时spring也会将其放入二级缓存。
4.通过initializeBean方法做后置工作
通过第3步,外层UserRightService就基本实例化完成了,同时也注入了自身的代理。
此时,调用initializeBean方法

方法里调用到applyBeanPostProcessorsAfterInitialization方法
然后又进入AbstractAutoProxyCreator类的方法
因为第3步往earlyProxyReferences成员变量中保存了UserRightService信息,所以红框出返回false,方法直接返回原bean
5.取出二级缓存的代理
继续源码后面的逻辑。
第一个红框,通过getSingleton可以取出之前放入二级缓存的代理。
第二个红框,由于initializeBean方法返回的exposedObject与bean是同一个对象,都是原生的UserRightService,所以if为true,将代理赋给exposedObject
6.加入容器
经过上述步骤,spring最终获取到的是UserRightService的代理对象,于是加入一级缓存。
结论
根据上面分析,我们得出结论
autowired注入自己的代理后,最后容器中的对象只有一个,而且是代理对象。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)