spring Bean的完整生命周期

2023-05-16

spring bean的完整生命周期

在这里插入图片描述

1.1 容器启动时

BeanFactoryPostProcessor->postProcessBeanFactory() ;
Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。同时可以定义BeanFactoryPostProcessor,通过设置’order’属性来确定各个BeanFactoryPostProcessor执行顺序。

1.2 实例化之后调用

InstantiationAwareBeanPostProcessor ->postProcessPropertyValues()

1.3 Bean初始化时

属性注入(setter)
BeanNameAware ->setBeanName()
BeanFactoryAware->setBeanFactory()
ApplicationContextAware->setApplicationContext()
BeanPostProcessor ->postProcessBeforeInitialization()
InitializingBean->afterPropertiesSet()
init-method属性
BeanPostProcessor->postProcessAfterInitialization()
DiposibleBean->destory()
destroy-method属性

1.4 容器刷新过程

容器刷新的过程可以细分为如下几个步骤

  • Spring应用上下文启动准备阶段
  • BeanFactory创建阶段
  • BeanFactory准备阶段
  • BeanFactory后置处理阶段
  • BeanFactory注册BeanPostProcessor阶段
  • 初始化内建Bean:MessageSource
  • 初始化内建Bean:Spring事件广播器
  • Spring应用上下文刷新阶段
  • Spring事件监听器注册阶段
  • BeanFactory初始化完成阶段
  • Spring应用上下文启动完成阶段

Spring应用上下文启动准备阶段
AbstractApplicationContext#prepareRefresh

  • 记录启动时间 startupDate
  • 设置标志为closed(false),active(true)
  • 初始化PropertySources
  • 校验Environment中必须属性
  • 初始化事件监听器集合
  • 初始化早期Spring事件集合

BeanFactory创建阶段
AbstractApplicationContext#obtainFreshBeanFactory

刷新Spring应用上下文底层BeanFactory(refreshBeanFactory)

  • 如果已存在BeanFactory,销毁Bean,并且关闭BeanFactory
  • 创建DefaultListableBeanFactory(一般情况下都是DefaultListableBeanFactory)
  • 设置BeanFactory id
  • 设置BeanFactory是否允许BeanDefinition重复定义,是否允许循环引用
  • 加载BeanDefinition
  • 关联新建的BeanFactory到Spring应用上下文
  • 返回Spring应用上下文底层BeanFactory(getBeanFactory)

BeanFactory准备阶段
AbstractApplicationContext#prepareBeanFactory

  • 关联ClassLoader
  • 设置Bean表达式处理器
  • 添加 PropertyEditorRegistrar 的实现 ResourceEditorRegistrar
  • 注册BeanPostProcessor(ApplicationContextAwareProcessor),用来处理Aware回调接口
  • 忽略Aware回调接口作为依赖注入接口
  • 注册ResolvableDependency对象-BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext
  • 注册BeanPostProcessor(ApplicationListenerDetector),用来处理ApplicationListener接口
  • 注册BeanPostProcessor(LoadTimeWeaverAwareProcessor),用来处理aop
  • 注册单例对象(Environment,Java System Properties以及OS环境变量)

BeanFactory后置处理阶段
如果想对BeanFactory进行扩展,可以通过如下2种方式

  • 子类重写AbstractApplicationContext#postProcessBeanFactory方法
  • 实现BeanFactoryPostProcessor接口

AbstractApplicationContext#invokeBeanFactoryPostProcessors 方法就是用来处理BeanFactoryPostProcessor接口的,调用的次序比较复杂,总结如下

  • BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(入参中的)
  • BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(容器中的,并且实现了PriorityOrdered接口)
  • BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(容器中的,并且实现了Ordered接口)
  • BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(容器中的,除去第2,3步剩余的BeanDefinitionRegistryPostProcessor)
  • BeanDefinitionRegistryPostProcessor#postProcessBeanFactory(所有BeanDefinitionRegistryPostProcessor接口实现类)
  • BeanFactoryPostProcessor#postProcessBeanFactory(入参数中的)
  • BeanFactoryPostProcessor#postProcessBeanFactory(容器中的,实现了PriorityOrdered接口)
  • BeanFactoryPostProcessor#postProcessBeanFactory(容器中的,实现了Ordered接口)
  • BeanFactoryPostProcessor#postProcessBeanFactory(容器中的,除去7,8步剩余的BeanFactoryPostProcessor)

注册BeanPostProcessor(ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor)

注册LoadTimeWeaverAwareProcessor对象

前面说过在容器初始化的过程中,往容器中注入了一个BeanFactoryPostProcessor接口的实现类即ConfigurationClassPostProcessor。

这是一个非常重要的BeanFactoryPostProcessor,通过@Bean、@Component、@ComponentScan、@Import、@ImportResource注入Bean的方式都由这个类来处理,对这些注解的实现感兴趣的小伙伴可以看一下这个类的源码

回调BeanFactoryPostProcessor接口的相关方法就搞这么多排序规则,有必要吗?

有必要,一方面是提高可扩展性,另外一方面是有些实现类的调用优先级必须要高一点,不然会有问题,我后面用例子演示

BeanFactory注册BeanPostProcessor阶段

  • 注册BeanPostProcessor(PostProcessorRegistrationDelegate.BeanPostProcessorChecker)
  • 注册PriorityOrdered类型的BeanPostProcessor
  • 注册Ordered类型的BeanPostProcessor
  • 注册普通的BeanPostProcessor
  • 注册MergedBeanDefinitionPostProcessor
  • 注册BeanPostProcessor(ApplicationListenerDetector)

此时注册到容器中的BeanPostProcessor有6个,这6个BeanPostProcessor在Spring Bean的生命周期中起着重要的作用,这个注册时机会影响后面调用的时机,所以搞优先级很有必要

spring 容器中的bean实例化后的完整生命周期一共分为十一步完成。

1.bean对象的实例化
2.封装属性,也就是设置properties中的属性值
3.如果bean实现了BeanNameAware,则执行setBeanName方法,也就是bean中的id值
4.如果实现BeanFactoryAware或者ApplicationContextAware ,需要设置setBeanFactory或者上下文对象setApplicationContext
5.如果存在类实现BeanPostProcessor后处理bean,执行postProcessBeforeInitialization,可以在初始化之前执行一些方法
6.如果bean实现了InitializingBean,则执行afterPropertiesSet,执行属性设置之后的操作
7.调用执行指定的初始化方法
8.如果存在类实现BeanPostProcessor则执行postProcessAfterInitialization,执行初始化之后的操作
9.执行自身的业务方法
10.如果bean实现了DisposableBean,则执行spring的的销毁方法
11.调用执行自定义的销毁方法。
第五步和第八步可以结合aop,在初始化执行之前或者执行之后执行一些操作。

以上就是springbean的完整生命周期.

public class Man implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean,
        BeanPostProcessor {
    private String name;

    public Man() {
        System.out.println("1 实例化");
    }

    public void setName(String name) {
        System.out.println("2 设置属性");
        this.name = name;
    }

    public void setUp() {
        System.out.println("7 执行自己配置的初始化方法");
    }

    public void run() {
        System.out.println("9 执行自身的业务方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("10 执行spring的销毁方法");
    }

    public void selfDefineDestroy() {
        System.out.println("11 执行自己配置的销毁方法");
    }

    public void setBeanName(String s) {
        System.out.println("3 设置bean的名称也就是spring容器中的名称,也就是id值" + name);
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("6 属性设置后执行的方法");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("4 设置ApplicationContext");
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("5 属性设置后执行的方法postProcessBeforeInitialization");
        return null;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("8 属性设置后执行的方法postProcessAfterInitialization");
        return null;
    }
}

applicationContext.xml中的配置

<bean id="man" class="com.itheima.ioc.springBeanlife.Man" init-method="setup" destroy-method="destory">
    <property name="name" value="张三"/>
</bean>

测试

@Test
public  void beanlifeTest(){
    ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    Man man=(Man)context.getBean("man");
    man.run();
    context.close();
}

结果

1 实例化
2 设置属性
3 设置bean的名称也就是spring容器中的名称,也就是id值zhangsan
4 设置ApplicationContext
6 属性设置后执行的方法
7 执行自己配置的初始化方法
9 执行自身的业务方法
10 执行spring的销毁方法
11 执行自己配置的销毁方法

深究Spring中Bean的生命周期

前言
这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了《Spring in action》这本书,书上有对Bean声明周期的大致解释,但是没有代码分析,所以就自己上网寻找资料,一定要把这个Bean生命周期弄明白!
一、Bean 的完整生命周期
在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。
相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程
在这里插入图片描述
Bean 的生命周期
如上图所示,Bean 的生命周期还是比较复杂的,下面来对上图每一个步骤做文字描述:

  1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
  2. Bean实例化后对将Bean的引入和值注入到Bean的属性中
  3. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
  4. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
  5. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
  6. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
  7. 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
  8. 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
  9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
  10. 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

上面是Spring 中Bean的核心接口和生命周期,面试回答上述过程已经足够了。但是翻阅JavaDoc文档发现除了以上接口外,还有另外的初始化过程涉及的接口:摘自org.springframework.beans.factory.BeanFactory, 全部相关接口如下,上述已有的就不用着重标注,把额外的相关接口着重标注下
在这里插入图片描述

Bean 完整的生命周期

文字解释如下:
————————————初始化————————————

  • BeanNameAware.setBeanName() 在创建此bean的bean工厂中设置bean的名称,在普通属性设置之后调用,在InitializinngBean.afterPropertiesSet()方法之前调用
  • BeanClassLoaderAware.setBeanClassLoader(): 在普通属性设置之后,InitializingBean.afterPropertiesSet()之前调用
  • BeanFactoryAware.setBeanFactory() : 回调提供了自己的bean实例工厂,在普通属性设置之后,在InitializingBean.afterPropertiesSet()或者自定义初始化方法之前调用
  • EnvironmentAware.setEnvironment(): 设置environment在组件使用时调用
  • EmbeddedValueResolverAware.setEmbeddedValueResolver(): 设置StringValueResolver 用来解决嵌入式的值域问题
  • ResourceLoaderAware.setResourceLoader(): 在普通bean对象之后调用,在afterPropertiesSet 或者自定义的init-method 之前调用,在 ApplicationContextAware 之前调用。
  • ApplicationEventPublisherAware.setApplicationEventPublisher(): 在普通bean属性之后调用,在初始化调用afterPropertiesSet 或者自定义初始化方法之前调用。在 ApplicationContextAware 之前调用。
  • MessageSourceAware.setMessageSource(): 在普通bean属性之后调用,在初始化调用afterPropertiesSet 或者自定义初始化方法之前调用,在 ApplicationContextAware 之前调用。
  • ApplicationContextAware.setApplicationContext(): 在普通Bean对象生成之后调用,在InitializingBean.afterPropertiesSet之前调用或者用户自定义初始化方法之前。在ResourceLoaderAware.setResourceLoader,ApplicationEventPublisherAware.setApplicationEventPublisher,MessageSourceAware之后调用。
  • ServletContextAware.setServletContext(): 运行时设置ServletContext,在普通bean初始化后调用,在InitializingBean.afterPropertiesSet之前调用,在 ApplicationContextAware 之后调用注:是在WebApplicationContext 运行时
  • BeanPostProcessor.postProcessBeforeInitialization() : 将此BeanPostProcessor 应用于给定的新bean实例 在任何bean初始化回调方法(像是InitializingBean.afterPropertiesSet或者自定义的初始化方法)之前调用。这个bean将要准备填充属性的值。返回的bean示例可能被普通对象包装,默认实现返回是一个bean。
  • BeanPostProcessor.postProcessAfterInitialization() : 将此BeanPostProcessor 应用于给定的新bean实例 在任何bean初始化回调方法(像是InitializingBean.afterPropertiesSet或者自定义的初始化方法)之后调用。这个bean将要准备填充属性的值。返回的bean示例可能被普通对象包装
  • InitializingBean.afterPropertiesSet(): 被BeanFactory在设置所有bean属性之后调用(并且满足BeanFactory 和 ApplicationContextAware)。
    ————————————销毁————————————
    在BeanFactory 关闭的时候,Bean的生命周期会调用如下方法:
  • DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(): 在销毁之前将此BeanPostProcessor 应用于给定的bean实例。能够调用自定义回调,像是DisposableBean 的销毁和自定义销毁方法,这个回调仅仅适用于工厂中的单例bean(包括内部bean)
  • 实现了自定义的destory()方法

Bean 的生命周期验证
为了验证Bean生命周期的过程,有两种形式:一种是为面试而准备的,一种是为了解全过程而准备的,下面来看代码:

Book.class

public class Book implements BeanNameAware, BeanFactoryAware,
        ApplicationContextAware, InitializingBean, DisposableBean {

    private String bookName;
    public Book(){
        System.out.println("1 Book Initializing ");
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("4 Book.setBeanFactory invoke");
    }

    public void setBeanName(String name) {
        System.out.println("3 Book.setBeanName invoke");
    }

    public void destroy() throws Exception {
        System.out.println("10 Book.destory invoke");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("7 Book.afterPropertiesSet invoke");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("5 Book.setApplicationContext invoke");
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
        System.out.println("2 setBookName: Book name has set.");
    }

    public void myPostConstruct(){
        System.out.println("8 Book.myPostConstruct invoke");
    }

    // 自定义初始化方法
    @PostConstruct
    public void springPostConstruct(){
        System.out.println("@PostConstruct");
    }

    public void myPreDestory(){
        System.out.println("11 Book.myPreDestory invoke");
        System.out.println("---------------destroy-----------------");
    }

    // 自定义销毁方法
    @PreDestroy
    public void springPreDestory(){
        System.out.println("@PreDestory");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("------inside finalize-----");
    }
}

自定义实现BeanPostProcessor 的MyBeanPostProcessor:

public class MyBeanPostProcessor implements BeanPostProcessor {

    // 容器加载的时候会加载一些其他的bean,会调用初始化前和初始化后方法
    // 这次只关注book(bean)的生命周期
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
        }
        return bean;
    }
}

在resources 目录下新建Bean-Lifecycle.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

      <!-- 扫描bean -->
    <context:component-scan base-package="com.bean.lifecycle"/>

    <!-- 实现了用户自定义初始化和销毁方法 -->
    <bean id="book" class="com.bean.lifecycle.Book" init-method="myPostConstruct" destroy-method="myPreDestory">
          <!-- 注入bean 属性名称 -->
        <property name="bookName" value="thingking in java" />
    </bean>

      <!--引入自定义的BeanPostProcessor-->
    <bean class="com.bean.lifecycle.MyBeanPostProcessor"/>

</beans>

做一个启动类的测试,新建SpringBeanLifecycleApplication

public class SpringBeanLifecycleApplication {

    public static void main(String[] args) throws InterruptedException {
        // 为面试而准备的Bean生命周期加载过程
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = " + book.getBookName());
        ((ClassPathXmlApplicationContext) context).destroy();

    }

}

启动测试,输出结果如下:

1 Book Initializing 
2 setBookName: Book name has set.
3 Book.setBeanName invoke
4 Book.setBeanFactory invoke
5 Book.setApplicationContext invoke
6 MyBeanPostProcessor.postProcessBeforeInitialization
7 Book.afterPropertiesSet invoke
8 Book.myPostConstruct invoke
9 MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java
10 Book.destory invoke
11 Book.myPreDestory invoke
---------------destroy-----------------

为了验证Bean完整的生命周期,需要新建一个SubBookClass 继承Book类

public class SubBookClass extends Book implements BeanClassLoaderAware,
        EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,
        ApplicationEventPublisherAware,MessageSourceAware{

    private String bookSystem;

    public String getBookSystem() {
        return bookSystem;
    }

    public void setBookSystem(String bookSystem) {
        System.out.println("设置BookSystem 的属性值");
        this.bookSystem = bookSystem;
    }

    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("SubBookClass.setBeanClassLoader() 方法被调用了");
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("SubBookClass.setApplicationEventPublisher() 方法被调用了");
    }

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("SubBookClass.setEmbeddedValueResolver() 方法被调用了");
    }

    public void setEnvironment(Environment environment) {
        System.out.println("SubBookClass.setEnvironment() 方法被调用了");
    }

    public void setMessageSource(MessageSource messageSource) {
        System.out.println("SubBookClass.setMessageSource() 方法被调用了");
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("SubBookClass.setResourceLoader() 方法被调用了");
    }

}

上述SubBookClass类与Book是互补关系。

新建一个SubBean-Lifecycle.xml,注入SubBookClass

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <bean id="bookClass" class="com.bean.lifecycle.SubBookClass" init-method="myPostConstruct" destroy-method="myPreDestory">
        <property name="bookSystem" value="Java System" />
    </bean>

    <bean class="com.bean.lifecycle.MyBeanPostProcessor"/>

</beans>

完整的SpringBeanLifecycleApplication 如下:

public class SpringBeanLifecycleApplication {

    public static void main(String[] args) throws InterruptedException {
        // 为面试而准备的Bean生命周期加载过程
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = " + book.getBookName());
        ((ClassPathXmlApplicationContext) context).destroy();

        // 完整的加载过程,当然了解的越多越好
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SubBean-Lifecycle.xml");
        SubBookClass subBookClass = (SubBookClass) applicationContext.getBean("bookClass");
        System.out.println("BookSystemName = " + subBookClass.getBookSystem());
        ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();
    }

}

输出完整的结果:

Book Initializing 
setBookName: Book name has set.
Book.setBeanName invoke
Book.setBeanFactory invoke
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
@PostConstruct
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java
@PreDestory
Book.destory invoke
Book.myPreDestory invoke
---------------destroy-----------------

Book Initializing 
设置BookSystem 的属性值
Book.setBeanName invoke
SubBookClass.setBeanClassLoader() 方法被调用了
Book.setBeanFactory invoke
SubBookClass.setEnvironment() 方法被调用了
SubBookClass.setEmbeddedValueResolver() 方法被调用了
SubBookClass.setResourceLoader() 方法被调用了
SubBookClass.setApplicationEventPublisher() 方法被调用了
SubBookClass.setMessageSource() 方法被调用了
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
BookSystemName = Java System
Book.destory invoke
Book.myPreDestory invoke
---------------destroy-----------------

spring bean 生命周期

spring IOC 源码分析

Spring的单例对象的初始化主要分为三步

在这里插入图片描述

  • createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象
  • populateBean:填充属性,这一步主要是多bean的依赖属性进行填充
  • initializeBean:调用spring xml中的init 方法。

springbean生命周期的构成

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

  • Bean自身的方法: 这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法
  • Bean级生命周期接口方法: 这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
  • 容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
  • 工厂后处理器接口方法: 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

spring bean的生命周期

就是穿插在spring bean 初始化三个步骤的中间,具体的流程见下面。黄色为主线,同颜色的表示同一个对象
在这里插入图片描述

spring IOC以及bean生命周期源码分析

以下组要通过分析spring ioc源码的方式让大家理解spring bean的生命周期,源码分析过程只保留主线,一些不相关或者不重要的代码都省去。建议大家按照这个主线自已单步调试一下。

1. 加载bean配置文件

ApplicationContext factory = new ClassPathXmlApplicationContext("application-context.xml");

ClassPathXmlApplicationContext 构造函数内部主要就调用了一个方法-refresh方法。refresh方法就包含了spring ioc的全部流程。下面我们详细的分析

2. refresh()方法

public void refresh() throws BeansException, IllegalStateException {
// 设置一些环境变量、创建Environment,准备工作
    prepareRefresh();
//创建beanFactory,加载BeanDefinition带beanFactory
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//beanFactory设置一些必要的信息
    prepareBeanFactory(beanFactory);
    try {
        postProcessBeanFactory(beanFactory);
//调用实现了BeanFactoryPostProcessor接口的postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(beanFactory);
//注册实现BeanPostProcessor接口的bean,相当于bean的拦截器
        registerBeanPostProcessors(beanFactory);
//国际化相关处理
        initMessageSource();
//初始化容器的广播时间
        initApplicationEventMulticaster();
        onRefresh();
// 注册listeners beans
        registerListeners();
// 实例bean,bean的生命周期大部分都在这个方法中
        finishBeanFactoryInitialization(beanFactory);
// 发布finish通知, 注册bean的生命周期bean
        finishRefresh();
    } catch (BeansException ex) {
        destroyBeans();
        cancelRefresh(ex);
    }
// 清空bean定义的一些元数据信息
    resetCommonCaches();
}

2.1 prepareRefresh()方法

protected void prepareRefresh() {
/*
其实这个方法里面什么也没有做,但是可以重写改方法,设置一些环境变量。比如WebApplicationContext的实现类中AbstractRefreshableWebApplicationContext中就设置了servlet的一些初始变量
*/
    initPropertySources();
/*
验证设置的环境变量是不是正确,有没有包含空值
*/
    getEnvironment().validateRequiredProperties();
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

2.2 obtainFreshBeanFactory()方法

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    return beanFactory;
}

2.2.1 refreshBeanFactory() 方法

@Override
protected final void refreshBeanFactory() throws BeansException {
// 创建BeanFactory
    DefaultListableBeanFactory beanFactory = createBeanFactory();
    beanFactory.setSerializationId(getId());
    customizeBeanFactory(beanFactory);
// 从xml文件或者注解加载BeanDefinition,存到DefaultListableBeanFactory的beanDefinitionMap字段
    loadBeanDefinitions(beanFactory);
}

2.3 prepareBeanFactory()方法

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //设置classLoader
    beanFactory.setBeanClassLoader(getClassLoader());
        //el表达式支持
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 添加BeanPostProcessor, 不知道干嘛用的
    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));    
//下面三个bean主要是系统的一些变量设置等等
    beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment())      
    beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()) 
    beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}

2.4 invokeBeanFactoryPostProcessors()方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {        
/*
这个方法里面的代码比较长,总的来说就是调用实现了BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor接口的中的方法。在调用的时候按照接口是否实现PriorityOrdered, Ordered, 和其余的顺序调用。
1、如果需要在修改添加等对BeanDefinition的操作的话,实现BeanDefinitionRegistryPostProcessor接口
2、如果统计bean的一些信息,修改bean在配置BeanDefinition中的属性值等,实现BeanFactoryPostProcessor接口
*/ 
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}

2.5 registerBeanPostProcessors()方法
与BeanFactoryPostProcessors类似,按一定的顺序注册实现BeanPostProcessor的接口
2.6 finishBeanFactoryInitialization()方法
// 实例化剩余的非lazy的bean,核心的代码都在这里面
beanFactory.preInstantiateSingletons()
2.6.1 preInstantiateSingletons() 方法

public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    for (String beanName : beanNames) {
//如果bean有父类,那么这个bean是可以合并的,需要把父类的相关信息比如属性和子类的合并。
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是FactoryBean
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                getBean(beanName);
            }
        }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

2.6.1.1 getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法
preInstantiateSingletons 会调用getBean(), getBean() 会调用doGetBean(),doGetBean()会调用getSingleton(),这是一个重要的方法,需要提出分析一下

Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
        // 如果singletonObject中没有创建好bean,就调用getObject方法。singletonFactory是函数接口,对应下面的createBean方法
     singletonObject = singletonFactory.getObject();
}
addSingleton(beanName, singletonObject);

2.6.1.1.1 createBean()

createBean(){
// Give BeanPostProcessors a chance to return a proxy instead of the target 
//在bean执行构造函数之前,给最后一个机会去执行一些操作,需要bean实现InstantiationAwareBeanPostProcessorAdapter接口
    Object bean = bean instance.resolveBeforeInstantiation(beanName, mbdToUse);
//创建bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}

2.6.1.1.1.1 doCreateBean()
//填充bean的属性,并且允许在设置bean属性值之前做一些操作,比如修改属性值

    populateBean(beanName, mbd, instanceWrapper);
/*
1、bean感知,调用setBeanName和setBeanFactory接口
2、执行init-method方法之前执行一些处理工作,对应的方法是postProcessBeforeInitialization
3、调用InitializingBean.afterPropertiesSet()方法
4、调用init-method方法
5、执行BeanPostProcessor的postProcessAfterInitialization方法
6、执行InstantiationAwareBeanPostProcessorAdapter的postProcessAfterInitialization方法
*/
    exposedObject = initializeBean(beanName, exposedObject, mbd);
//获取bean
    Object earlySingletonReference = getSingleton(beanName, false);
//注册bean的DisposableBean(销毁使用)
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
    ```
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring Bean的完整生命周期 的相关文章

随机推荐

  • 附录2:CentOS 下载

    以语雀 文档为准 视频演示 点击查看 bilibili CentOS Vault Mirror CentOS 7 8 最新版 xff08 含各大云厂商的镜像 xff09 CentOS 7 http isoredirect centos or
  • 附录3:Anolis 龙蜥 下载

    以语雀 文档为准 视频演示 点击查看 bilibili 官网 xff1a https openanolis cn 7 7 正式版 https mirrors openanolis cn anolis 7 7 isos GA x86 64 7
  • 附录4:Ubuntu 乌班图 下载

    以语雀 文档为准 https releases ubuntu com https old releases ubuntu com releases 版本号 版本代号 下载地址 14 04 5 Trusty Tahr https old re
  • 小工具1:tcping

    以语雀 文档为准 说明 tcping exe 是一个控制台应用程序 xff0c 其操作类似于 ping xff0c 但它在tcp端口上工作 在 Windows 上要查看指定 IP 端口 是否连通 xff0c 通常要使用 telnet xff
  • 小工具2:Windows curl.exe

    以语雀 文档为准 GitHub 仓库 xff1a https github com curl curlGitHub 仓库 Windows 版 xff1a https github com curl curl for win下载页面 xff1
  • 小工具3:Windows tail.exe

    以语雀 文档为准 文件 xff1a tail zip xff0c 文件来源于网络 xff0c 用于实时查看文件内容 xff0c 与 Linux 的 tail 有相同的用法 下载上述文件 xff0c 解压 xff0c 将 tail exe 放
  • 小工具4:Windows cports.exe

    以语雀 文档为准 文件 cports zip xff0c 文件来源于网络 xff0c 用于实时查看端口占用情况 xff0c 使用管理员权限运行时 xff0c 可杀端口 下载上述文件 xff0c 解压 xff0c 将 cports exe 放
  • 为何在 node 项目中使用固定版本号,而不使用 ~、^?

    以语雀 文档为准 使用 时吃过亏希望版本号掌握在自己手里 xff0c 作者自己升级 xff08 跟随官方进行升级 xff0c 就算麻烦作者 xff0c 也不想麻烦使用者 xff09 虽然 pnpm 很好用 xff0c 但是不希望在项目中用到
  • 导读 2、kubernetes(k8s)导读

    以语雀 文档为准 内容来自 Kubernetes 权威指南 第5版等 kubernetes 是什么 xff1f kubernetes是一个全新的基于容器技术的分布式架构领先方案 xff0c 是容器云的优秀平台选型方案 xff0c 已经成为新
  • 区块链——脱坑truffle

    使用truffle构建一个智能合约 实现输出 helloworld 的功能 网上有很多帖子 但也有很多坑 这里展示我的搭建过程 帮助大家绕过那些麻烦 一 安装web3 solc truffle npm g install solc npm
  • 使用fescar遇到can not register RM,err:can not connect to fescar-server.

    前提 如果你看到了这篇文章 xff0c 说明你已经成功跑起了阿里爸爸fescar官方提供的example和server xff0c 并且你的客户端和服务端之间心跳正常 xff0c 但是当客户端进行事务操作时却提示以下错误 com span
  • Arch常用软件

    常用软件 开发 gitandroid studiovim 图形界面 网络 pacman S networkmanager 启动其提供的服务 systemctl start NetworkManager service 让服务开机自启 sys
  • CentOS可以使用的yum仓库地址

    name 61 CentOS 6 6 Base baseurl 61 http mirrors aliyun com centos vault 6 6 os x86 64 gpgcheck 61 1 gpgkey 61 http mirro
  • pyqt错误:Unresolved reference 和 正确安装pycharm+python+pyqt5

    写如下代码 xff1a span class hljs keyword import span sys span class hljs keyword from span PyQt5 span class hljs keyword impo
  • 以下是adb工具包最新Google官方版下载地址:

    以下是adb工具包最新Google官方版下载地址 xff1a ADB和Fastboot for Windows https dl google com android repository platform tools latest win
  • java.lang.UnsupportedOperationException 及resultMap相关知识

    起因 今天在请求数据库数据时报错java lang UnsupportedOperationException xff0c 从字面上理解错误的含义就是不支持的操作异常 xff0c 后面定位到错误发生在数据库sql语句中 xff0c 具体原因
  • Spring Boot配置类处理

    ConfigurationClassPostProcessor处理所有配置类 xff0c 包括 64 Component 64 Bean 64 Import注解等 由于配置类可能会引入新的配置类 xff0c 新的配置类也需要被处理 xff0
  • 数据库范式1NF 2NF 3NF详细阐述

    范式 xff1a 关系数据库中的关系是要满足一定要求的 xff0c 满足不同程度要求的不同范式 满足最低要求的叫第一范式 xff0c 简称1NF xff0c 在第一范式中满足进一步要求的为第二范式 xff0c 其余以此类推 通俗来说是满足数
  • 记一次 Native Crash Abort message:‘FORTIPY :vsprintf:prevented 33-byte write into 32-byte buffer ’

    先贴上关键日志 第一眼看到日志 xff0c 以为是缺少了Arm64 的so文件 xff0c 查看后发现并没缺少 xff1b 无奈之下 xff0c 只有复现这个Crash xff0c 一点点缩小排查范围 xff1b 最终将问题的矛头指向了项目
  • spring Bean的完整生命周期

    spring bean的完整生命周期 1 1 容器启动时 BeanFactoryPostProcessor gt postProcessBeanFactory Spring IoC容器允许BeanFactoryPostProcessor在容