首页 > 其他分享 >Spring容器系列-bean的生命周期

Spring容器系列-bean的生命周期

时间:2024-06-17 21:34:18浏览次数:10  
标签:生命周期 name mbd Spring beanName bean scope null

Spring容器系列-bean的生命周期

    bean 的生命周期从调用 beanFactory 的 getBean 开始,到这个 bean 被销毁,可以总结为以下七个阶段:

    1.  处理名称,检查缓存

    2. 处理父子容器

    3. 处理 dependsOn

    4. 选择 scope 策略

    5. 创建 bean

    6. 类型转换处理

    7. 销毁 bean

    下面我们看AbstractBeanFactory#doGetBean方法来依次讲解:

  1  protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
  2      //1.处理bean名称解析
  3      String beanName = this.transformedBeanName(name);
  4      //检查是否存在缓存中,一级二级三级
  5      Object sharedInstance = this.getSingleton(beanName);
  6      Object beanInstance;
  7      //从单例缓存中判断是否存在这个示例,可能来源于Spring启动的时候,也有可能来源于Spring 启动时初始化了非懒加载的对象
  8      if (sharedInstance != null && args == null) {
  9          if (this.logger.isTraceEnabled()) {
 10              if (this.isSingletonCurrentlyInCreation(beanName)) {
 11                  this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
 12              } else {
 13                  this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 14              }
 15          }
 16          //如果单例工厂存在这个bean,则通过调用getObject方法获取bean实例
 17          beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
 18      } else {
 19          //如果当前线程存在这个实例,则抛出异常
 20          if (this.isPrototypeCurrentlyInCreation(beanName)) {
 21              throw new BeanCurrentlyInCreationException(beanName);
 22          }
 23          //2.获取当前bean工厂的父工厂,然后获取bean,此处是递归查找
 24          BeanFactory parentBeanFactory = this.getParentBeanFactory();
 25          if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
 26              String nameToLookup = this.originalBeanName(name);
 27              if (parentBeanFactory instanceof AbstractBeanFactory) {
 28                  
 29                  return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
 30              }
 31  
 32              if (args != null) {
 33                  //调用父工厂的getBean方法
 34                  return parentBeanFactory.getBean(nameToLookup, args);
 35              }
 36  
 37              if (requiredType != null) {
 38                  //根据类型获取bean
 39                  return parentBeanFactory.getBean(nameToLookup, requiredType);
 40              }
 41  
 42              return parentBeanFactory.getBean(nameToLookup);
 43          }
 44          //如果参数为检查类型,则设置名称为beanName的bean实例已经创建的标识
 45          if (!typeCheckOnly) {
 46              this.markBeanAsCreated(beanName);
 47          }
 48  
 49          StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
 50  
 51          try {
 52              if (requiredType != null) {
 53                  beanCreation.tag("beanType", requiredType::toString);
 54              }
 55  
 56              RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
 57              this.checkMergedBeanDefinition(mbd, beanName, args);
 58              //3.获取bean的依赖属性
 59              String[] dependsOn = mbd.getDependsOn();
 60              String[] var12;
 61              if (dependsOn != null) {
 62                  var12 = dependsOn;
 63                  int var13 = dependsOn.length;
 64  
 65                  for(int var14 = 0; var14 < var13; ++var14) {
 66                      String dep = var12[var14];
 67                      //检查是否存在循环依赖
 68                      if (this.isDependent(beanName, dep)) {
 69                          throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 70                      }
 71                      //向注册器中注册这个依赖的bean
 72                      this.registerDependentBean(dep, beanName);
 73  
 74                      try {
 75                          //获取并解决当前bean
 76                          this.getBean(dep);
 77                      } catch (NoSuchBeanDefinitionException var31) {
 78                          throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
 79                      }
 80                  }
 81              }
 82              //根据 scope 处理当前bean
 83              if (mbd.isSingleton()) {
 84                  sharedInstance = this.getSingleton(beanName, () -> {
 85                      try {
 86                          return this.createBean(beanName, mbd, args);
 87                      } catch (BeansException var5) {
 88                          this.destroySingleton(beanName);
 89                          throw var5;
 90                      }
 91                  });
 92                  beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 93              } else if (mbd.isPrototype()) {
 94                  var12 = null;
 95  
 96                  Object prototypeInstance;
 97                  try {
 98                      this.beforePrototypeCreation(beanName);
 99                      prototypeInstance = this.createBean(beanName, mbd, args);
100                  } finally {
101                      this.afterPrototypeCreation(beanName);
102                  }
103  
104                  beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
105              } else {
106                  String scopeName = mbd.getScope();
107                  if (!StringUtils.hasLength(scopeName)) {
108                      throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
109                  }
110                  //5.类型转换
111                  Scope scope = (Scope)this.scopes.get(scopeName);
112                  if (scope == null) {
113                      throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
114                  }
115  
116                  try {
117                      Object scopedInstance = scope.get(beanName, () -> {
118                          this.beforePrototypeCreation(beanName);
119  
120                          Object var4;
121                          try {
122                              var4 = this.createBean(beanName, mbd, args);
123                          } finally {
124                              this.afterPrototypeCreation(beanName);
125                          }
126  
127                          return var4;
128                      });
129                      beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
130                  } catch (IllegalStateException var30) {
131                      throw new ScopeNotActiveException(beanName, scopeName, var30);
132                  }
133              }
134          } catch (BeansException var32) {
135              beanCreation.tag("exception", var32.getClass().toString());
136              beanCreation.tag("message", String.valueOf(var32.getMessage()));
137              //清除创建bean
138              this.cleanupAfterBeanCreationFailure(beanName);
139              throw var32;
140          } finally {
141              beanCreation.end();
142          }
143      }
144  
145      return this.adaptBeanInstance(name, beanInstance, requiredType);
146  }

   DefaultSingletonBeanRegistry#getSingleton方法:

   通过调用getSingleton方法,这里针对单例对象会检查一级、二级、三级缓存

 1  //singletonObjects 一级缓存,存放单例成品对象
 2  private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
 3  //singletonFactories 三级缓存,存放单例工厂对象
 4  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
 5  //earlySingletonObjects 二级缓存,存放单例工厂的产品对象
 6  private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
 7  @Nullable
 8  protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 9      Object singletonObject = this.singletonObjects.get(beanName);
10      if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
11          singletonObject = this.earlySingletonObjects.get(beanName);
12          if (singletonObject == null && allowEarlyReference) {
13              synchronized(this.singletonObjects) {
14                  singletonObject = this.singletonObjects.get(beanName);
15                  if (singletonObject == null) {
16                      singletonObject = this.earlySingletonObjects.get(beanName);
17                      if (singletonObject == null) {
18                          ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
19                          if (singletonFactory != null) {
20                              singletonObject = singletonFactory.getObject();
21                              this.earlySingletonObjects.put(beanName, singletonObject);
22                              this.singletonFactories.remove(beanName);
23                          }
24                      }
25                  }
26              }
27          }
28      }
29      return singletonObject;
30  }

   2. 处理父子容器

   1)如果当前容器根据名字找不到这个 bean,此时若父容器存在,则执行父容器的 getBean 流程

   2)父子容器的 bean 名称可以重复

   3. 处理 dependsOn

   1)如果当前 bean 有通过 dependsOn 指定了非显式依赖的 bean,这一步会提前创建这些 dependsOn 的 bean

   2)所谓非显式依赖,就是指两个 bean 之间不存在直接依赖关系,但需要控制它们的创建先后顺序

   4. 选择 scope 策略

   

 1  if (mbd.isSingleton()) {
 2      //如果是单例类型的bean,通过调用createBean方法尽心创建,
 3      sharedInstance = this.getSingleton(beanName, () -> {
 4          try {
 5              return this.createBean(beanName, mbd, args);
 6          } catch (BeansException var5) {
 7              //如果创建bean发生异常,则由于当前bean可能被添加在单例池中,调用销毁方法销毁当前bean
 8              this.destroySingleton(beanName);
 9              throw var5;
10          }
11      });
12      beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
13  } else if (mbd.isPrototype()) {
14      var12 = null;
15      //如果当前bean是多例的,则实时创建
16      Object prototypeInstance;
17      try {
18          //在threadlocal中设置这个bean的标志位,防止同一个线程重复创建bean造成资源浪费
19          this.beforePrototypeCreation(beanName);
20          //创建bean实例
21          prototypeInstance = this.createBean(beanName, mbd, args);
22      } finally {
23          //清除threadlocal标志位
24          this.afterPrototypeCreation(beanName);
25      }
26  
27      beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
28  } else {
29      //处理bean的作用范围为 request、session的bean
30      String scopeName = mbd.getScope();
31      if (!StringUtils.hasLength(scopeName)) {
32          throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
33      }
34  
35      Scope scope = (Scope)this.scopes.get(scopeName);
36      if (scope == null) {
37          throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
38      }
39  
40      try {
41          Object scopedInstance = scope.get(beanName, () -> {
42              this.beforePrototypeCreation(beanName);
43  
44              Object var4;
45              try {
46                  var4 = this.createBean(beanName, mbd, args);
47              } finally {
48                  this.afterPrototypeCreation(beanName);
49              }
50  
51              return var4;
52          });
53          beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
54      } catch (IllegalStateException var30) {
55          throw new ScopeNotActiveException(beanName, scopeName, var30);
56      }
57  }

 

标签:生命周期,name,mbd,Spring,beanName,bean,scope,null
From: https://www.cnblogs.com/hld123/p/18253244

相关文章

  • spring面试题
    Spring框架中都用到了哪些设计模式?工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;单例模式:Bean默认为单例模式。代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;模板方法:用来解决代码重复的问题。比如.RestTemplate,JmsTemplate,JpaTemp......
  • javab每日一题:在spring里有哪些常用注解?
     Spring框架提供了许多注解,用于简化配置、管理Bean、处理事务、处理AOP等。以下是一些在Spring中常用的注解以及它们的作用:@ComponentScan:作用:用于启用组件扫描,指定要扫描的基础包。Spring会自动扫描并注册带有@Component及其派生注解(@Service、@Repository、@Controller......
  • 毕业设计——基于springboot的电力巡检系统
    !!!有需要的小伙伴可以通过文章末尾名片咨询我哦!!! ......
  • 毕业设计——基于SpringBoot的个人博客系统
    !!!有需要的小伙伴可以通过文章末尾名片咨询我哦!!! ......
  • 基于Springboot框架班级综合测评管理系统的设计与实现
    开头语:你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。开发语言:Java数据库:MySQL技术:Springboot框架,B/S模式工具:MyEclipse系统展示首页个人中心学生管理综合测评管理摘要随着互联网技术的高速发展,班级综合测评管理系统应运而生,旨在实现学校管......
  • SpringBoot的Security和OAuth2的使用
    创建项目先创建一个spring项目。然后编写pom文件如下,引入spring-boot-starter-security,我这里使用的springboot是2.4.2,这里使用使用spring-boot-dependencies,在这里就能找到对应的security的包。<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.......
  • Spring容器系列-启动原理(下)
    Spring容器系列-启动原理(下)  从上一篇文章《Spring容器系列-启动原理(上)》中,介绍了Spring容器初始化的核心方法refresh()的整体情况。这篇文章来详细展开介绍。其中比较重要的方法会标记上***  一、refresh中的12个方法  1. prepareRefresh  主要作用:记录下容器......
  • Spring-AOP概述
    1.AOP的基本概念AOP:面向切面编程(AspectOrientedProgramming),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术AOP的作用:利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发效率没......
  • 基于springboot的南门桥社区疫情防疫系统-48138(免费领源码+数据库)可做计算机毕业设计J
    Springboot南门桥社区疫情防疫系统的设计与实现摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对南门桥社区疫情防疫系统等问题,对南门桥社区......
  • Docker+Jenkins+Pipline实现SpringBoot项目input选择不同差异性yml文件打包、执行sh打
    场景Docker+Jenkins+Pipline如何获取git插件环境变量(提交sha、分支等)以及Jenkinsfile中获取sh执行结果(获取git最近提交信息):https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/139697004在上面的基础上实现了使用Jenkinsfile文件获取git的提交记录以及获取sh的执......