Spring-bean的生命周期-尾篇

上回说到阶段9,现在我们接着往下说

阶段10:所有单例bean初始化完成后阶段

所有单例bean实例化完成之后,spring会回调下面这个接口:

java 复制代码
package org.springframework.beans.factory;

public interface SmartInitializingSingleton {
   public void afterSingletonsInstantiated();
}

调用逻辑在下面这个方法中

java 复制代码
/**
* 确保所有非lazy的单例都被实例化,同时考虑到FactoryBeans。如果需要,通常在工厂设置结束时调用。
*/
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

这个方法内部会先触发所有非延迟加载的单例bean初始化,然后从容器中找到类型是SmartInitializingSingleton 的bean,调用他们的 afterSingletonsInstantiated 方法。

来个案例

java 复制代码
package com.shiguiwu.springmybatis.spring.lifecycle.allbeaninit;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @description: 10所有bean初始化完成
 * 注意是非懒加载的bean初始化完成
 * @author: stone
 * @date: Created by 2021/3/28 13:35
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.allbeaninit
 */
@ComponentScan
public class AllBeanInitTests {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//        Arrays.stream(context.getBeanDefinitionNames()).forEach(b -> System.out.println(context.getBean(b)));
        context.register(AllBeanInitTests.class);
        System.out.println("开始启动容器!");
        context.refresh();
        System.out.println("容器启动完毕!");
    }
}

打印结果

java 复制代码
开始启动容器!
14:00:04.770 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26
14:00:04.903 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
14:00:05.473 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [G:\workspace\ideaWorkspace\spring-mybatis\target\classes\com\shiguiwu\springmybatis\spring\lifecycle\allbeaninit\Bean1.class]
14:00:05.474 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [G:\workspace\ideaWorkspace\spring-mybatis\target\classes\com\shiguiwu\springmybatis\spring\lifecycle\allbeaninit\Bean2.class]
14:00:05.483 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [G:\workspace\ideaWorkspace\spring-mybatis\target\classes\com\shiguiwu\springmybatis\spring\lifecycle\allbeaninit\MySmartInitializingSingleton.class]
14:00:05.571 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
14:00:05.586 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
14:00:05.588 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
14:00:05.591 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
14:00:05.673 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'allBeanInitTests'
14:00:05.683 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
14:00:05.683 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
14:00:05.684 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mySmartInitializingSingleton'
SmartInitializingSingleton#afterSingletonsInstantiated========================
容器启动完毕!

阶段11:Bean使用阶段

这个阶段就不说了,调用getBean方法得到了bean之后,大家可以随意使用,任意发挥。

阶段12:Bean销毁阶段

触发bean销毁的几种方式

  1. 调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
  2. 调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
  3. 调用ApplicationContext中的close方法

Bean销毁阶段会依次执行

  1. 轮询beanPostProcessors列表,如果DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction方法
  2. 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
  3. 调用bean自定义的销毁方法

DestructionAwareBeanPostProcessor 接口

java 复制代码
package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
    //bean销毁前调用的方法
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
    //用来判断bean是否需要触发postProcessBeforeDestruction方法
    default boolean requiresDestruction(Object bean) {
        return true;
    }
}

这个接口有个关键的实现类:

java 复制代码
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor#postProcessBeforeDestruction方法中会调用bean中所有标注了@PreDestroy的方法。

再来说一下自定义销毁方法有3种方式

方式1:xml中指定销毁方法

xml 复制代码
<bean destroy-method="bean中方法名称"/>

方式2:@Bean中指定销毁方法

java 复制代码
@Bean(destroyMethod = "初始化的方法")

方式3:api的方式指定销毁方法

this.beanDefinition.setDestroyMethodName(methodName);

初始化方法最终会赋值给下面这个字段

java 复制代码
org.springframework.beans.factory.support.AbstractBeanDefinition#destroyMethodName

来个案例

java 复制代码
package com.shiguiwu.springmybatis.spring.lifecycle.destroy;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;

/**
 * @description: 销毁时调用的代码
 * @author: stone
 * @date: Created by 2021/3/28 14:55
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.destroy
 */
public class MyDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor {
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        System.out.println("准备销毁bean:" + beanName);
    }

    @Override
    public boolean requiresDestruction(Object bean) {
        System.out.println("是否调用。。。。。。。");
        return true;
    }
}

测试代码

java 复制代码
package com.shiguiwu.springmybatis.spring.lifecycle.destroy;

import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;

/**
 * @description: 12销毁阶段
 *
 * 1. 调用
 * org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyB
 * ean
 * 2. 调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
 * 3. 调用ApplicationContext中的close方法
 *
 * 顺序
 * 1. @PreDestroy标注的所有方法
 * 2. DisposableBean接口中的destroy()
 * 3. 自定义的销毁方法
 * @author: stone
 * @date: Created by 2021/3/28 13:59
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.destroy
 */
public class DestroyTests {

    public static void main(String[] args) {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());
        //将CommonAnnotationBeanPostProcessor加入
        factory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor()); //@2

        AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(Integer.class)
                .addConstructorArgValue(12)
                .getBeanDefinition();
        AbstractBeanDefinition definition1 = BeanDefinitionBuilder.genericBeanDefinition(Integer.class)
                .addConstructorArgValue(12)
                .getBeanDefinition();
        AbstractBeanDefinition definition3 = BeanDefinitionBuilder.genericBeanDefinition(A.class)
                .getBeanDefinition();
        //设置销毁方法
        definition3.setDestroyMethodName("destroy1");

        factory.registerBeanDefinition("shuzi", definition);
        factory.registerBeanDefinition("shuzi1", definition1);
        factory.registerBeanDefinition("A", definition3);
        //触发所有单列初始化
        factory.preInstantiateSingletons();

        //销毁一个
        factory.destroySingleton("shuzi");

        System.out.println("销毁所有的bean");
        factory.destroySingletons();

        //关闭容器
    }
}

打印结果

java 复制代码
14:29:38.611 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'shuzi'
是否调用。。。。。。。
是否调用。。。。。。。
14:29:38.922 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'shuzi1'
是否调用。。。。。。。
是否调用。。。。。。。
14:29:38.923 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'A'
是否调用。。。。。。。
准备销毁bean:shuzi
销毁所有的bean
准备销毁bean:A
preDestroy() 
destroy() 
destroy1() 自定义的。。。。。。。。 
准备销毁bean:shuzi1

实际上ApplicationContext内部已经将spring内部一些常见的必须的 BeannPostProcessor 自动装配到beanPostProcessors列表中 ,比如我们熟悉的下面的几个

1.org.springframework.context.annotation.CommonAnnotationBeanPostProcessor用来处理@Resource、@PostConstruct、@PreDestroy的

2.org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor用来处理@Autowired、@Value注解

3.org.springframework.context.support.ApplicationContextAwareProcessor

用来回调Bean实现的各种Aware接口

下面来说一个非常非常重要的类,打起精神,一定要注意看。
AbstractApplicationContext类(非常重要的类)

BeanFactory接口

这个我们已经很熟悉了,Bean工厂的顶层接口
DefaultListableBeanFactory类

实现了BeanFactory接口,可以说这个可以是BeanFactory接口真正的唯一实现,内部真正实现了bean生命周期中的所有代码。其他的一些类都是依赖于DefaultListableBeanFactory类,将请求转发给DefaultListableBeanFactory进行bean的处理的。
其他3个类

我们经常用到的就是这3个类:

AnnotationConfigApplicationContext/ClassPathXmlApplicationContext/FileSystemXmlApplicationContext这3个类,他们的主要内部的功能是依赖他的父类AbstractApplicationContext来实现的,所以大家主要看AbstractApplicationContext 这个类。

AbstractApplicationContext类

这个类中有2个比较重要的方法

java 复制代码
public abstract ConfigurableListableBeanFactory getBeanFactory() throws
IllegalStateException;
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory
beanFactory)

大家是否注意过我们使用 AnnotationConfigApplicationContext 的时候,经常调用 refresh方法 ,这个方法内部就会调用上面这2个方法

第一个方法:getBeanFactory()

返回当前应用上下文中的 ConfigurableListableBeanFactory ,这也是个接口类型的,这个接口有一个唯一的实现类: DefaultListableBeanFactory 。有没有很熟悉,上面说过:DefaultListableBeanFactory是BeanFactory真正的唯一实现。应用上线文中就会使用这个 ConfigurableListableBeanFactory 来操作spring容器。

第二个方法:registerBeanPostProcessors
说的通俗点:这个方法就是向ConfigurableListableBeanFactory中注册BeanPostProcessor,内容会从spring容器中获取所有类型的BeanPostProcessor,将其添加到DefaultListableBeanFactory#beanPostProcessors列表中

看一下这个方法的源码:

java 复制代码
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

会将请求转发给PostProcessorRegistrationDelegate#registerBeanPostProcessors 。内部比较长,大家可以去看一下源码,这个方法内部主要用到了4个BeanPostProcessor 类型的List集合。

List priorityOrderedPostProcessors = new ArrayList<>();

List orderedPostProcessors

List nonOrderedPostProcessors;

List internalPostProcessors = new ArrayList<>();

先说一下:当到方法的时候,spring容器中已经完成了所有Bean的注册。

spring会从容器中找出所有类型的BeanPostProcessor列表,然后按照下面的规则将其分别放到上面的4个集合中,上面4个集合中的 BeanPostProcessor 会被依次添加到DefaultListableBeanFactory#beanPostProcessors列表中,来看一下4个集合的分别放的是那些BeanPostProcessor

priorityOrderedPostProcessors(指定优先级的BeanPostProcessor)

实现org.springframework.core.PriorityOrdered接口的BeanPostProcessor,但是不包含MergedBeanDefinitionPostProcessor类型的
orderedPostProcessors(指定了顺序的BeanPostProcessor)

实现了org.springframework.core.annotation.Order接口的BeanPostProcessor,但是不包含MergedBeanDefinitionPostProcessor类型的
nonOrderedPostProcessors(未指定顺序的BeanPostProcessor)

上面2中类型置为以及MergedBeanDefinitionPostProcessor之外的internalPostProcessors

MergedBeanDefinitionPostProcessor类型的BeanPostProcessor列表。

大家可以去看一下 CommonAnnotationBeanPostProcessor 和

AutowiredAnnotationBeanPostProcessor ,这两个类都实现了 PriorityOrdered 接口,但是他们也实现了MergedBeanDefinitionPostProcessor 接口,所以最终他们会被丢到

internalPostProcessors 这个集合中,会被放入BeanPostProcessor的最后面。

此致,spring bean生命周期完整的流程结束,附上完整的流程图!!完结,我好累

相关推荐
徐*红18 分钟前
java 线程池
java·开发语言
尚学教辅学习资料18 分钟前
基于SSM的养老院管理系统+LW示例参考
java·开发语言·java毕设·养老院
2401_8576363918 分钟前
计算机课程管理平台:Spring Boot与工程认证的结合
java·spring boot·后端
1 9 J20 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
Code apprenticeship21 分钟前
Java面试题(2)
java·开发语言
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
憨子周1 小时前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨3 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java