关于java:Spring-Bean生命周期源码精要分析

49次阅读

共计 6481 个字符,预计需要花费 17 分钟才能阅读完成。

概述

生命周期大抵分为四步, 当然源代码的作者没有分这么分明,次要是为了了解不便,创立 bean 的次要流程代码在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance.doCreateBean

  1. 实例化筹备
  2. 实例化
  3. 属性注入
  4. 初始化

实例化筹备

对于一般 java 对象来说,创建对象只需四步

  1. 编译 Java 文件,生成.class 文件
  2. 收到 new 或者反射创立一个对象的信号
  3. 将 class 文件通过类加载器加载进 JVM 虚拟机
  4. 初始化对象可供使用

而 Bean 对象不同,Bean 能够通过 xml 定义,能够通过注解(@Component@Configuration等)定义。

SpringBoot 启动时,依据 @ComponentScan 的范畴扫描,并把定义封装进 BeanDefinition 实例,其中有定义的很多元数据,如 @Scope@Lazy 等等,最初把收集的 BeanDefinition 放入 beanDefinitionMap 中,key 是 beanName,value 是 BeanDefinition 对象。

万恶之源:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

1. 通过 bean 名字获取 BeanDefinition

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

2. 调用 BeanPostProcessors 对 bean 的元信息进行解决(个别不必

try {
  // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  if (bean != null) {return bean;}
}

3. 调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean 创立 bean

try {Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean'" + beanName + "'");
  }
  return beanInstance;
}

从而进入 doCreateBean 进行实例化

实例化

1.SpringBoot 先查问缓存,如果缓存中没有再实例化 bean。

实例化的代码如下#createBeanInstance

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}

2. 实例实现后,BeanPostProcessor 进行后处理,这是为了查找出满足条件的属性、办法, 将他们封装起来, 以便前面在填充属性的时候能够间接应用。#applyMergedBeanDefinitionPostProcessors

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {
    try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    }
    catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                      "Post-processing of merged bean definition failed", ex);
    }
    mbd.postProcessed = true;
  }
}

3. 将这个 bean 退出到三级缓存中。#addSingletonFactory

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

属性注入

代码如下#populateBean

// Initialize the bean instance.
Object exposedObject = bean;
try {populateBean(beanName, mbd, instanceWrapper);
  exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;
  }
  else {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  }
}

留神到属性注入后,有这么一段代码

if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name'" + beanName + "'has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been" +
                                "wrapped. This means that said other beans do not use the final version of the" +
                                "bean. This is often the result of over-eager type matching - consider using" +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

这段代码是判断缓存中的 bean 和本人创立的 bean 的地址是否雷同,如果不同,就会接着判断!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName), 如果为 true,就会抛异样。

初始化

在初始化过程,能够设置很多的 Hook。

Aware 接口

Aware 接口也叫感知接口,实现这个接口的类能够

  • BeanNameAware 取得到容器中 Bean 的名称
  • BeanFactoryAware 取得以后 bean Factory, 从而调用容器的服务
  • ApplicationContextAware 取得以后的 application context 从而调用容器的服务
  • MessageSourceAware 失去 message source 从而失去文本信息
  • ApplicationEventPublisherAware 利用工夫公布器, 用于公布事件
  • ResourceLoaderAware 获取资源加载器, 能够取得内部资源文件

BeanPostProcessor

用法:实现 BeanPostProcessor 接口并重写办法

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
        return bean;
    }

}

源码解析

其余

其余的接口差不多都很简略了,请自行 review。

要害源码办法(强烈建议本人去撸一遍)

  • org.springframework.context.support.AbstractApplicationContext#refresh(入口)
  • org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization(初始化单例对象入口)
  • org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons(初始化单例对象入口)
  • org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)(万恶之源,获取并创立 Bean 的入口)
  • org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean(理论的获取并创立 Bean 的实现)
  • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)(从缓存中尝试获取)
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])(实例化 Bean)
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean(实例化 Bean 具体实现)
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance(具体实例化过程)
  • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory(将实例化后的 Bean 增加到三级缓存)
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(实例化后属性注入)
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)(初始化入口)

参考文章

  • 怎么了解 spring bean 的生命周期,理论利用场景?
  • Spring 源码剖析 - 八、applyMergedBeanDefinitionPostProcessors 源码剖析

正文完
 0