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生命周期完整的流程结束,附上完整的流程图!!完结,我好累

相关推荐
ChinaRainbowSea3 分钟前
十六,Spring Boot 整合 Druid 以及使用 Druid 监控功能
java·spring boot·后端·spring·web
吴半杯14 分钟前
Mysql调优之性能监控(一)
java·linux·mysql
.生产的驴31 分钟前
Docker 消息队列RabbitMQ 安装延迟消息插件
运维·spring boot·后端·docker·容器·rabbitmq·java-rabbitmq
慢慢雨夜1 小时前
uniapp 苹果安全域适配
java·前端·uni-app
mit6.8241 小时前
[Linux#49][UDP] 2w字详解 | socketaddr | 常用API | 实操:实现简易Udp传输
linux·网络·c++·笔记·后端
敲代码不忘补水1 小时前
二十种编程语言庆祝中秋节
java·javascript·python·golang·html
码农研究僧1 小时前
Java或者前端 实现中文排序(调API的Demo)
java·前端·localecompare·中文排序·collator
Chase-Hart1 小时前
【每日一题】LeetCode 7.整数反转(数学)
java·数据结构·算法·leetcode·eclipse
四角小裤儿儿1 小时前
Java数据结构(十一)——归并排序、计数排序
java·数据结构·排序算法
guangzhi06331 小时前
JVM本地方法栈
java·jvm·面试