spring中autowired注入自己的代理后,最后容器中的对象是原对象还是代理对象

问题场景

假设类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注入自己的代理后,最后容器中的对象只有一个,而且是代理对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值