Spring Bean生命周期源码精要分析

概述

生命周期大致分为四步,当然源代码的作者没有分这么清楚,主要是为了理解方便,创建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 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,就会抛异常。

初始化

Spring Bean生命周期源码精要分析_第1张图片

在初始化过程,可以设置很多的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)(初始化入口)

参考文章

你可能感兴趣的:(javaspring后端)