首页 > 其他分享 >spring中bean的生命周期

spring中bean的生命周期

时间:2023-04-10 17:56:49浏览次数:36  
标签:生命周期 依赖 spring bean 缓存 orderService UserService public

背景

bean在创建过程中会出现各种各样的循环依赖。了解spring如何用三级缓存机制解决循环依赖,解决spring没有解决的循环依赖。所以需要了解bean的生命周期原理。

出现属性的循环依赖时,bean的生命周期

spring用三级缓存机制来解决属性的循环依赖。

以 UserService 和 OrderService 出现属性的循环依赖为例子。

示例代码

@Component  
public class OrderService {  
  
   @Autowired
   UserService userService;
}

@Component  
public class UserService {  
  
   @Autowired
   OrderService orderService;
}

orderService 添加入set集合

private final Set<String> singletonsCurrentlyInCreation =  
      Collections.newSetFromMap(new ConcurrentHashMap<>(16));

singletonsCurrentlyInCreation 存储正在创建的 beanName ,后面用来检查是否出现了循环依赖。

这里把 "orderService" 添加进这集合。

gh

创建bean的普通对象

createBeanInstance 中推断构造函数,然后实例化bean并返回

instanceWrapper = createBeanInstance(beanName, mbd, args);

gh

将 orderService 添加到三级缓存中

三级缓存 singletonFactories 存储的是一个lambda 表达式。这个表达式用来存储 生成 orderService 对象的过程。后面出现循环依赖的时候会用到

private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

gh

orderService 属性填充

populateBean 会给 orderService 做属性填充,把 UserService 填充进去。在这里,会进入 UserService 的生命周期。

populateBean(beanName, mbd, instanceWrapper);

gh

三级缓存中生成 orderService

UserService 的生命周期的步骤同上 orderService 的生命周期。
这里直接看到给 UserService 的bean生命周期中,对 字段 orderService 的属性注入过程。

这里需要把 orderService 从三级缓存中获取出来,然后放入二级缓存,如果需要AOP 这里会提前进行 AOP。

(注:这里二级缓存是为了,防止 UserService 出现多个循环依赖时,不生成多个代理对象。而存在,这里就不放开解释了。)

...
// 从 三级缓存 singletonFactories 里面找  
// 获取到 lambda 表达式  
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);  
if (singletonFactory != null) {  
   // 执行 lambda 表达式  
   singletonObject = singletonFactory.getObject();  
   // 把结果放到 二级缓存 earlySingletonObjects 里面  
   this.earlySingletonObjects.put(beanName, singletonObject);
...

gh

这里从三级缓存中获取到 orderService 并完成 UserService 的生命周期。

orderService 的AOP阶段

这里如果循环依赖提前进行了AOP 就不会再进行AOP获取代理对象了。

earlyProxyReferences 缓存的就是 执行lambda 表达式获取的 bean

private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);

gh

orderService 放入单例池

因为出现了循环依赖所以从二级缓存中获取bean,放入单例池

gh

把 orderService 从 set集合中删除

orderService 的生命周期结束,已经不是正在创建的 bean。所以这里把 orderService 从 set集合中 remove。

gh

构造方法的循环依赖解决

构造方法的循环依赖,spring的三级缓存机制是解决不了的

因为卡在了创建普通对象,构造方法执行不了,普通对象都创建不成功

@Component  
public class DemoAService {  
  
   public  DemoAService(DemoBService demoBService) {
   
   }
  
}

@Component  
public class DemoBService {  
  
   public  DemoBService(DemoAService demoAService) {
   
   } 
  
}

但是 加上 @Lazy 注解可以解决

@Lazy 不真正创建对象,返回一个代理对象。用的时候才会创建对象。
普通对象创建不成功,不影响

这里加上一个 @Lazy 就能解决

@Component  
public class DemoAService {  

	@Lazy
	public  DemoAService(DemoBService demoBService) {
	   
	}
  
}

@Component  
public class DemoBService {  

   	public  DemoBService(DemoAService demoAService) {
	   
	}
  
}

async 注解的循环依赖

同上。

给属性加上 @Lazy 之后,不存在循环依赖了。

加上 @Lazy 创建代理对象,执行的时候才会真正的创建对象。

标签:生命周期,依赖,spring,bean,缓存,orderService,UserService,public
From: https://www.cnblogs.com/xiaosiyuan88888888/p/17303747.html

相关文章

  • spring中事务的原理
    背景spring在使用事务的时候会出现事务失效的情况。这里了解spring中事务原理,以及事务失效的原理和解决方案。原因spring中事务是基于AOP的,如果不是代理对象执行的话就不会有事务。比如,加上@Transactional的事务方法,是被包裹起来的。publicclassUserServiceProxyextends......
  • SpringMVC怎么实现web端上传超大文件
    ​ 一、功能性需求与非功能性需求要求操作便利,一次选择多个文件和文件夹进行上传;支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传。刷新页面后继续传输。关闭浏览器后保留进度信息。支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务......
  • 13-springcloud-eureka-9-Eureka集群注册中心打包发布
    在实际项目中,需要将Eureka发布到具体服务器上进行部署,打包部署其实和SpringBoot里面的一样,我们可以把其达成jar包,启动时对于properties文件,不同的环境激活不同的配置文件;运行:java-jarspringcloud-service-eureka.jar--spring.profiles.active=eureka8761java-jarspringclo......
  • 动力节点王鹤SpringBoot3笔记——第六章 远程访问@HttpExchange[SpringBoot 3]
    第六章 远程访问@HttpExchange[SpringBoot3]远程访问是开发的常用技术,一个应用能够访问其他应用的功能。SpringBoot提供了多种远程访问的技术。基于HTTP协议的远程访问是支付最广泛的。SpringBoot3提供了新的HTTP的访问能力,通过接口简化HTTP远程访问,类似Feign功能。Spring......
  • spring注解整合mybatis
    引入依赖<!--mybatis-spring与mybatis使用低版本适配--><!--https://mvnrepository.com/artifact/org.mybatis/mybatis-spring--><dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version&......
  • Spring Security系列教程-初识Spring Security
    前言在开始学习SpringSecurity系列教程之前,小千先带大家来了解一下SpringSecurity,看看它到底是什么,有哪些功能,有什么特点,以及它与别的同类框架相比,有什么不同,我们以后学习任何一个新技术,其实都可以遵循"3W1H"法则,这样学习起来才能更有条理。一.SpringSecurity概念首先请各位跟......
  • 【Spring MVC】第一个程序
    添加Maven依赖:<!--spring核心类--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.8.RELEASE</version></dependency>&......
  • MIT 6.5840 2023 Spring(6.824)LAB1:MapReduce
    MIT6.58402023Spring(6.824)LAB1:MapReduce前言本次lab主要是完成一个基于RPC远程调用的单机单文件系统的简单MapReduce框架,并完成单词计数任务。基于golang实现,单Master,多Worker。实现worker的奔溃恢复(FaultTorrance),通过超时重新执行实现。主要的任务有,RPC调用参数及返回参数......
  • SpringBoot处理get请求的路径参数
    当请求方式为get并且使用路径参数的时候,请求格式形如: 后端controller中可以用实体类接收参数,并且不用添加任何注解,当然这个实体类是中的属性是有getter和setter方法的才行,接受方式形如:实体类形如: SpringBoot会自动做处理,将路径参数中的值填充到实体类对应的属性中......
  • Spring
    1.springboot的自动装配原理springboot启动以后:通过@EnableAutoConigration里的@lmport(AutoConfigurationlmportSelector.class)实现配置类的导入,但是并不是传统意义上的单个导入,而是批量进行导入AutoConfigurationlmportSelector类实现了ImpotSelector接口,重写了selectlmport......