Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4681
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 90
  • 用 户 组: 普通用户
  • 注册时间: 2023-07-18 09:31
文章分类

全部博文(8)

文章存档

2023年(8)

我的朋友
最近访客

分类: Java

2023-08-17 08:56:09

1.spring bean的生命周期

1.1简介

有很多关于SPRING BEAN生命周期介绍的文章,有个比较通用的总结。那就是
实例化 -> 属性赋值 -> 初始化 -> 销毁
我觉得按照这个来理解要方便很多,下面将结合代码来理解这个流程。

下面是类图,结合类图来理解




我用了AnnotationConfigApplicationContext(估计现在用这个的比较多,本人没细看过springboot的代码,但理论上用的应该也是注解方式)。
入口其实就是AbstractApplicationContext的refresh方法,里面内容很多,不一一赘述,核心直接到{BANNED}{BANNED}{BANNED}最佳佳佳终的bean生产的地方AbstractAutowireCapableBeanFacotry.doCreateBean,代码如下

点击(此处)折叠或打开

  1. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  2.             throws BeanCreationException {

  3.         // Instantiate the bean.
  4.         BeanWrapper instanceWrapper = null;
  5.         if (mbd.isSingleton()) {
  6.             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  7.         }
  8.         if (instanceWrapper == null) {
  9.             instanceWrapper = createBeanInstance(beanName, mbd, args); //bean的实例化
  10.         }
  11.         Object bean = instanceWrapper.getWrappedInstance();
  12.         Class<?> beanType = instanceWrapper.getWrappedClass();
  13.         if (beanType != NullBean.class) {
  14.             mbd.resolvedTargetType = beanType;
  15.         }

  16.         // Allow post-processors to modify the merged bean definition.
  17.         synchronized (mbd.postProcessingLock) {
  18.             if (!mbd.postProcessed) {
  19.                 try {
  20.                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  21.                 }
  22.                 catch (Throwable ex) {
  23.                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  24.                             "Post-processing of merged bean definition failed", ex);
  25.                 }
  26.                 mbd.postProcessed = true;
  27.             }
  28.         }

  29.         // Eagerly cache singletons to be able to resolve circular references
  30.         // even when triggered by lifecycle interfaces like BeanFactoryAware.
  31.         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  32.                 isSingletonCurrentlyInCreation(beanName));
  33.         if (earlySingletonExposure) {
  34.             if (logger.isTraceEnabled()) {
  35.                 logger.trace("Eagerly caching bean '" + beanName +
  36.                         "' to allow for resolving potential circular references");
  37.             }
  38.             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  39.         }

  40.         // Initialize the bean instance.
  41.         Object exposedObject = bean;
  42.         try {
  43.             populateBean(beanName, mbd, instanceWrapper); //bean的属性赋值
  44.             exposedObject = initializeBean(beanName, exposedObject, mbd); //bean的初始化
  45.         }
  46.         catch (Throwable ex) {
  47.             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  48.                 throw (BeanCreationException) ex;
  49.             }
  50.             else {
  51.                 throw new BeanCreationException(
  52.                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  53.             }
  54.         }

  55.         if (earlySingletonExposure) {
  56.             Object earlySingletonReference = getSingleton(beanName, false);
  57.             if (earlySingletonReference != null) {
  58.                 if (exposedObject == bean) {
  59.                     exposedObject = earlySingletonReference;
  60.                 }
  61.                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  62.                     String[] dependentBeans = getDependentBeans(beanName);
  63.                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
  64.                     for (String dependentBean : dependentBeans) {
  65.                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  66.                             actualDependentBeans.add(dependentBean);
  67.                         }
  68.                     }
  69.                     if (!actualDependentBeans.isEmpty()) {
  70.                         throw new BeanCurrentlyInCreationException(beanName,
  71.                                 "Bean with name '" + beanName + "' has been injected into other beans [" +
  72.                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  73.                                 "] in its raw version as part of a circular reference, but has eventually been " +
  74.                                 "wrapped. This means that said other beans do not use the final version of the " +
  75.                                 "bean. This is often the result of over-eager type matching - consider using " +
  76.                                 "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
  77.                     }
  78.                 }
  79.             }
  80.         }

  81.         // Register bean as disposable.
  82.         try {
  83.             registerDisposableBeanIfNecessary(beanName, bean, mbd);
  84.         }
  85.         catch (BeanDefinitionValidationException ex) {
  86.             throw new BeanCreationException(
  87.                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  88.         }

  89.         return exposedObject;
  90.     }

1.2 实例化

没什么特别的貌似,回头再看看,只是找到合适的构造函数来进行实例化。

1.3 属性赋值

构造器注入
setter注入
autowire方式

1.4 初始化

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)这个代码很多,就不贴出来了,这里面大概做了几个重要的事情


1.执行aware接口,如果你实现了的话。
2.执行了BeanPostProcessor,这是一个容器级别的扩展,也就是你如果实现了这个接口,你会发现所有的bean初始化都会执行此接口。以下是我写的一个样例,那么下面2个方法有什么区别么。一个是init-method之前被调用,一个是在init-method后被调用。 这里聊下PostContruct这个标签,其实用的就是CommonAnnotationBeanPostProcessor这个来实现的
3.执行了init-method,这个就不多谈了。
由此我们引入了一个重要的东西,spring bean的扩展点。详细见后面



2.SPRING BEAN生命周期扩展点

2.1简介

大部分在前面bean生命周期都已经介绍了,主要集中在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

2.1bean自身方法

比如setter/getter等,你可以用settler来注入,不过这个是发生在属性注入的时候。
比如init-method或者destory等。

2.2容器级接口BeanPostProcessor接口

容器级也就是你实现了这个接口,所有的bean在生命周期时候都会调用到此接口的实现

2.3Bean级生命周期方法

BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean等,这个就是每个bean自己独立去实现。

3.三级缓存

  • 3.1简介

  1. singletonObjects, 一级缓存:存放已经完整生成好的bean,也就是初始化做完的bean.在获取bean时候优先从一级缓存中去找。
  2. earlySingletonObjects, 二级缓存:存放已经实例化的bean,但还没有初始化
  3. singletonFactories 三级缓存:存储singleFactory,其实是bean工厂,此时其实bean工厂里面的bean已经被实例化了
关于存在的意义(或者设计成这样的目的)。

一级缓存:{BANNED}{BANNED}最佳佳好理解,完整BEAN总要有个地方放吧。
二级缓存和三级缓存:都是为了解决循环依赖的,想想bean生命周期  实例化 -> 属性赋值 -> 初始化。 循环依赖是发生在属性赋值的时候,那要解决这个问题,那就必需在实例化完之后,就能让其它的bean可以找到他,也就是要找一个地方放不完整的bean,此时就再需要一个缓存了,这就是三级缓存的作用。那为什么还有一个二级缓存呢?和AOP有关,一开始实例化创建好了一个不完整的bean放在三级缓存中了。后来这个不完整的bean 就被别人给用了。这个时候又发生了AOP,后面这个被人给应用的bean其实就废了。所以AOP需要提前,这个时候就要找个地方放这个已经被增强过的BEAN。
阅读(79) | 评论(0) | 转发(0) |
0

上一篇:线程池

下一篇:记一次JVM调优

给主人留下些什么吧!~~