美文网首页
Spring Bean的生命周期

Spring Bean的生命周期

作者: 淡淡的橙子 | 来源:发表于2018-04-19 16:16 被阅读0次

最近在浏览Spring的源码。对于Spring来讲,Bean的生命周期是很重要的一个知识,了解了生命周期后我们就能对许多概念或者问题有了自己的了解,比如之前自己经常会有疑问的:Spring的Bean的初始化过程是先全都实例化,在进行初始化,还是一个一个完成实例化,初始化的整个过程等问题。

1. 主流程

spring的主流程主要集中在AbstractApplicationContext#refresh()方法上(插一句口,整个Spring的核心是BeanFactory,那这个ApplicationContext又是什么东西呢,通过代码我们实际可以看到,ApplicationContext实际采用的Decorator装饰器模式将BeanFactory封装起来的,这样就可以用于隐藏内部逻辑):

// 同步启动容器或者销毁容器
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
// 做一些准备,置一些状态位
            prepareRefresh();
// 这个是比较重要的一步,加载所有Bean Definition,也就是先加载Bean的定义,这样之后的BeanFactory就能获取诸如getBeanDefination,getBeanNamesForType等方法。
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 注册初始化的内容,比如默认的后置处理器PostProcessor等内容
            prepareBeanFactory(beanFactory);

            try {
// 模板方法,允许在bean实例化前对beanfactory进行修改。
                postProcessBeanFactory(beanFactory);
// 实例化BeanFactoryPostProcessor实现类(在Spring中,查找某一个接口或类的实现方式,是通过BeanFactory的findNamesForType等寻找,只要BeanDefination加载完毕即可)。执行BeanFactoryPostProcessor#postProcessBeanFactory方法,因此可见该方法是早于所有Bean的实例化而晚于所有BeanDefinition的加载的
                invokeBeanFactoryPostProcessors(beanFactory);
// 实例化BeanPostProcessor
                registerBeanPostProcessors(beanFactory);
// 为容器初始化Message源,即不同语言的消息体,国际化处理
                initMessageSource();
// 初始化应用消息广播器,并放在applicationEventMultcaster的bean中
                initApplicationEventMulticaster();
// 执行一些额外的方法,供子类来重写,模板方法的应用
                onRefresh();
// 在所有注册的bean中查找Listener bean,注册到消息广播器中
                registerListeners();
// 重要,实例化并初始化所有非lazy-init的类
                finishBeanFactoryInitialization(beanFactory);
// 做一些结尾的事情,比如清理某些cache,发布ContextRefreshEvent等。
                finishRefresh();
            }
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
// 如果遇到异常,则销毁beans
                destroyBeans();
                cancelRefresh(ex);
                // Propagate exception to caller.
                throw ex;
            }
            finally {
                resetCommonCaches();
            }
        }
    }

2. 生命周期流程图

spring的bean的生命周期

3. 说明

有几点需要说明:

  1. 加载BeanDefinition和实例化Bean:
    Bean的加载实际分为两个主要的步骤的:第一步是全部加载BeanDefinition,也就是所有Bean的定义,依据不同的方式,比如从xml中读取或者读取注解。第二部便是依次实例化和初始化各个Bean。
    别看仅仅只有这么两大部,里面却涉及到大量的逻辑与内容。
    我们就拿第一步加载中BeanDefinition为例,在AbstractApplicationContext#refresh() obtainFreshBeanFactory()中我们进行的是加载BeanDefinition。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 在这一步我们进行了加载
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

在refreshBeanFactory()中我们进行配置文件的加载并生成BeanDefinition。

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

其中DefaultListableBeanFactory beanFactory = createBeanFactory()中便是加载配置文件的过程。加载的最终结果就是生成了spring的核心容器beanFactory。读取配置文件的过程是一个非常庞大的工作,因为要解析各个标签。比如当我们配置有<context:component-scan/>时,对应的解析规则实际是org.springframework.context.annotation.ComponentScanAnnotationParser类,每一个标签对应了不同的解析类。也有着不同的解析规则,比如引入上了上面的标签时,在parse()的时候,不光会扫描相应的base-package下的类,同时还会将

Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);

也就是将AutowiredAnnotationBeanPostProcessor等后置处理器注入到了beanFactory中,这样就能在createBean的通过后置处理器,能够对@autowired的属性进行注入。

  1. 循环依赖的问题:
    Spring的核心之一DI,在面临循环依赖的时候可能存在些问题,比如类A依赖类B,类B依赖类C,而类C又依赖类A这种问题。对于Spring来讲,循环依赖分为三种情况:
  • 构造器循环依赖:无解。
  • singleton setter循环依赖:通过提前暴露FactoryObject的方法解决。
  • scop=prototype循环依赖:由于prototype作用域的bean,由于没有提前暴露bean的信息,所有自然也无法解决循环依赖的问题。
  1. 依赖的加载问题:
    如果我们类A依赖类B,那么在加载类A的时候的顺序是如何的呢?
    首先容器会进行A的实例化,然后在进行属性填入(populate)的时候,发现存在依赖B,而如果此时B还没有实例化的话,则会先去实例化B,并进行注入属性和初始化,完成之后才会继续A的属性填入,之后再完成A的初始化。整个顺序是这个样子的。

4. 参考

相关文章

网友评论

      本文标题:Spring Bean的生命周期

      本文链接:https://www.haomeiwen.com/subject/asswkftx.html