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

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot,可以通过@Autowired注解来从Spring容器获取对象。首先,确保你的类被Spring容器管理,可以使用@Component或者@Service等注解进行标记。然后,在需要获取对象的地方,使用@Autowired注解将对象注入进来。这样,Spring Boot会自动从容器找到对应的对象注入到你的类。例如,假设你想获取名为"beanId"的对象,你可以在需要使用该对象的地方使用@Autowired注解进行注入,如下所示: @Autowired private BeanType bean; 其,BeanType是你要获取的对象的类型,bean是你给该对象起的变量名。这样,Spring Boot会自动将名为"beanId"的对象注入到bean变量,你就可以在类使用该对象了。 #### 引用[.reference_title] - *1* [spring boot获取spring容器的bean对象](https://blog.csdn.net/qq_29235677/article/details/119652555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Spring Boot获取通过@Bean注入Spring容器对象实体](https://blog.csdn.net/weixin_42146366/article/details/102633076)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值