spring注解驱动开发-(6)-Spring的生命周期以及初始化和销毁方法

(1). Bean的创建

bean的创建实际上就是指 构造方法的调用;

singleton(单例)bean -容器初始化时会预先调用, 除非标注了 @Lazy 注解指定懒加载(延迟创建);

prototype(原型)bean -当第一次调用 getBean方法时, 才会调用构造方法

(2). Bean的初始化和销毁-4种方法

bean的初始化, 指的是在构造方法调用之后, 对象的一些初始化操作;

bean的销毁, 指的是在spring容器关闭前, 对bean对象做的一些后续处理操作的调用;

Bean的初始化和销毁有一下几种方法:

(2.1) @Bean注解指定initMethod/destroyMethod;

bean: 普通java类, 其中定义了 方法名: init close

package com.niewj.bean;

public class LifeTestBean1 {
    private String value;

    public LifeTestBean1(String value){
        System.out.println("LifeTestBean1-初始化!");
        this.value = value;
    }

    public void init(){
        System.out.println("LifeTestBean1#init-调用!");
    }

    public void close(){
        System.out.println("LifeTestBean1#close-调用!");
    }
}

Life1Config配置类中: 通过 @Bean 的属性 指定了初始化和销毁方法:

  • initMethod=”init”
  • destroyMethod=”close”
package com.niewj.config;

import com.niewj.bean.LifeTestBean1;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Life1Config {

    @Bean(value = "lifeBean1", initMethod = "init", destroyMethod = "close")
    public LifeTestBean1 lifeTestBean(){
        return  new LifeTestBean1("bean1");
    }
}

测试用例: testLifecycle

package com.niewj;

import com.niewj.bean.LifeTestBean1;
import com.niewj.config.Life1Config;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.stream.Stream;

/**
 * spring生命周期.
 */
public class LifecycleTest {

    @Test
    public void testLifecycle() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Life1Config.class);

        // 打印spring容器中的 BeanDefinition
        Stream.of(ctx.getBeanDefinitionNames()).forEach(e-> System.out.println(e));
        System.out.println("=============================");
        LifeTestBean1 bean = ctx.getBean(LifeTestBean1.class);

        System.out.println(bean);

        ctx.close();
    }
}

​ 可以看到:

  • 构造方法会预先调用(单例bean);
  • 然后init方法被调用;
  • 最后上下文关闭时, close方法也被调用!
LifeTestBean1-初始化!
LifeTestBean1#init-调用!
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
life1Config
lifeBean1
=============================
com.niewj.bean.LifeTestBean1@7d3a22a9
LifeTestBean1#close-调用!

(2.2) InitializingBean/DisposableBean 接口;

bean: LifeTestBean2 implements InitializingBean, DisposableBean

package com.niewj.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * 实现 InitializingBean && DisposableBean
 */
public class LifeTestBean2 implements InitializingBean, DisposableBean {
    private String value;

    public LifeTestBean2(String value){
        System.out.println("LifeTestBean2-初始化!");
        this.value = value;
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("LifeTestBean2#DisposableBean#destroy-调用!");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("LifeTestBean2#InitializingBean#afterPropertiesSet-调用!");
    }
}

配置类: Life2Config:

package com.niewj.config;

import com.niewj.bean.LifeTestBean2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Life2Config {

    @Bean
    public LifeTestBean2 lifeTestBean(){
        return  new LifeTestBean2("bean2");
    }
}

测试用例:

    @Test
    public void testLifecycle2() {
        // 1. 通过bean实现 InitializingBean和DisposableBean接口
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Life2Config.class);

        // 打印spring容器中的 BeanDefinition
        Stream.of(ctx.getBeanDefinitionNames()).forEach(e-> System.out.println(e));
        System.out.println("=============================");
        LifeTestBean2 bean = ctx.getBean(LifeTestBean2.class);

        System.out.println(bean);

        ctx.close();
    }

output:

  • 构造方法调用(singleton 容器预先初始化);
  • InitializingBean#afterPropertiesSet调用;
  • 工厂关闭前: DisposableBean#destroy调用;
LifeTestBean2-初始化!
LifeTestBean2#InitializingBean#afterPropertiesSet-调用!
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
life2Config
lifeTestBean
=============================
com.niewj.bean.LifeTestBean2@7d3a22a9
LifeTestBean2#DisposableBean#destroy-调用!

(2.3) @PostConstruct/@PreDestroy 注解(JSR250);

bean: LifeTestBean3 注解: @PreDestroy PostConstruct

package com.niewj.bean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 通过 JSR250注解 @PostConstruct && @PreDestroy
 */
public class LifeTestBean3 {
    private String value;

    public LifeTestBean3(String value) {
        System.out.println("LifeTestBean3-初始化!");
        this.value = value;
    }

    @PreDestroy
    public void doDestroy() {
        System.out.println("LifeTestBean3#doDestroy-调用!");
    }

    @PostConstruct
    public void doInit() {
        System.out.println("LifeTestBean3#doInit-调用!");
    }
}

配置类:

package com.niewj.config;

import com.niewj.bean.LifeTestBean3;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Life3Config {

    @Bean
    public LifeTestBean3 lifeTestBean() {
        return new LifeTestBean3("bean3");
    }
}

测试用例:

    @Test
    public void testLifecycle3() {
        // 1. 通过 JSR250注解 @PostConstruct && @PreDestroy
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Life3Config.class);

        // 打印spring容器中的 BeanDefinition
        Stream.of(ctx.getBeanDefinitionNames()).forEach(e-> System.out.println(e));
        System.out.println("=============================");
        LifeTestBean3 bean = ctx.getBean(LifeTestBean3.class);

        System.out.println(bean);

        ctx.close();
    }

output:

  • 构造方法调用;
  • @PostConstruct标注的方法调用;
  • 上下文关闭时; @PreDestroy标注的方法被调用;
LifeTestBean3-初始化!
LifeTestBean3#doInit-调用!
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
life3Config
lifeTestBean
=============================
com.niewj.bean.LifeTestBean3@2a32de6c
LifeTestBean3#doDestroy-调用!

(2.4) BeanPostProcessor接口(作用范围广);

此接口对所有扫描到的bean都起作用:

实现: BeanPostProcessor 接口:

  • before-init : postProcessBeforeInitialization(Object bean, String beanName)
  • after-init: postProcessAfterInitialization(Object bean, String beanName)
package com.niewj.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 通过 BeanPostProcessor 接口
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        System.out.println("MyBeanPostProcessor-初始化!");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessBeforeInitialization-调用!->beanName=" + beanName + "; bean=" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessAfterInitialization-调用!->beanName=" + beanName + "; bean=" + bean);
        return bean;
    }
}

com.niewj.bean包下一个普通类:

package com.niewj.bean;

import org.springframework.stereotype.Component;

/**
 * 普通bean+@Component
 */
@Component
public class LifeTestBean4 {

    public LifeTestBean4() {
        System.out.println("LifeTestBean4-初始化!");
    }
}

配置类: Life4Config:

扫描范围: @ComponentScan(“com.niewj.bean”)

包括: LifeTestBean4.java && MyBeanPostProcessor.java

package com.niewj.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.niewj.bean")
public class Life4Config {

}

用例: 注册配置类: Life4Config

    @Test
    public void testLifecycle4() {
        // 1. 通过 实现 BeanPostProcesser 接口
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Life4Config.class);

        // 打印spring容器中的 BeanDefinition
        Stream.of(ctx.getBeanDefinitionNames()).forEach(e-> System.out.println(e));
        System.out.println("=============================");

        ctx.close();
    }

output: 观察控制台:

MyBeanPostProcessor: postProcessBeforeInitialization/postProcessAfterInitialization

LifeTestBean4: postProcessBeforeInitialization/postProcessAfterInitialization

MyBeanPostProcessor-初始化!
MyBeanPostProcessor#postProcessBeforeInitialization-调用!->beanName=life4Config; bean=com.niewj.config.Life4Config$$EnhancerBySpringCGLIB$$684530bf@27c86f2d
MyBeanPostProcessor#postProcessAfterInitialization-调用!->beanName=life4Config; bean=com.niewj.config.Life4Config$$EnhancerBySpringCGLIB$$684530bf@27c86f2d
LifeTestBean4-初始化!
MyBeanPostProcessor#postProcessBeforeInitialization-调用!->beanName=lifeTestBean4; bean=com.niewj.bean.LifeTestBean4@197d671
MyBeanPostProcessor#postProcessAfterInitialization-调用!->beanName=lifeTestBean4; bean=com.niewj.bean.LifeTestBean4@197d671
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
life4Config
lifeTestBean4
myBeanPostProcessor
=============================

(2.5) bean的初始化小结

初始化和销毁有四种方式:

1. @Bean注解指定属性 initMethod/destroyMethod;

2. 普通bean实现 InitializingBean/DisposableBean接口;

3. 普通bean方法上标注 @PostConstruct/@PreDestroy注解;

4. 通用方法: 实现接口 BeanPostProcessor;

(2.6) 问题来了: 4种方式的优先级顺序是如何的?

上实例: LifeTestBeanAll.java

其中包含:

1.@PostConstruct/@PreDestroy 注解;

2.InitializingBean, DisposableBean接口的实现;

3.@Bean 指定 initMethod/destroyMethod方法;

4.MyBeanPostProcessor实现(在下方);

package com.niewj.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 普通bean+@Component
 */
@Component
public class LifeTestBeanAll implements InitializingBean, DisposableBean {

    public LifeTestBeanAll() {
        System.out.println("LifeTestBeanAll 构造方法调用!");
    }

    @PostConstruct
    public void postConstruct(){
        System.out.println("LifeTestBeanAll#@PostConstruct 调用");
    }

    @PreDestroy
    public void preDestroy(){
        System.out.println("LifeTestBeanAll#@PreDestroy 调用");
    }

    public void init(){
        System.out.println("LifeTestBeanAll#@Bean(initMethod) 调用");
    }

    public void close(){
        System.out.println("LifeTestBeanAll#@Bean(destroyMethod) 调用");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("LifeTestBeanAll#Disposable 调用~~");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("LifeTestBeanAll#InitializingBean#调用!~");
    }
}

MyBeanPostProcessor:

package com.niewj.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 通过 BeanPostProcessor 接口
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        System.out.println("MyBeanPostProcessor-初始化!");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessBeforeInitialization-调用!->beanName=" + beanName + "; bean=" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessAfterInitialization-调用!->beanName=" + beanName + "; bean=" + bean);
        return bean;
    }
}

配置类:

package com.niewj.config;

import com.niewj.bean.LifeTestBeanAll;
import com.niewj.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.niewj.bean")
public class LifeAllConfig {

    @Bean(initMethod = "init", destroyMethod = "close")
    public LifeTestBeanAll lifeTestBeanAll(){
        return new LifeTestBeanAll();
    }
}

测试用例:

    @Test
    public void testLifecycleAll() {
        // 注释掉 LifeTestBean4#@Component以防干扰
        // 1. 通过 实现 BeanPostProcesser 接口
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(LifeAllConfig.class);

        // 打印spring容器中的 BeanDefinition
        Stream.of(ctx.getBeanDefinitionNames()).forEach(e-> System.out.println(e));
        System.out.println("=============================");

        ctx.close();
    }

output: 关键地方来了:

MyBeanPostProcessor-初始化!
MyBeanPostProcessor#postProcessBeforeInitialization-调用!->beanName=lifeAllConfig; bean=com.niewj.config.LifeAllConfig$$EnhancerBySpringCGLIB$$77052e36@3d121db3
MyBeanPostProcessor#postProcessAfterInitialization-调用!->beanName=lifeAllConfig; bean=com.niewj.config.LifeAllConfig$$EnhancerBySpringCGLIB$$77052e36@3d121db3
LifeTestBeanAll 构造方法调用!
MyBeanPostProcessor#postProcessBeforeInitialization-调用!->beanName=lifeTestBeanAll; bean=com.niewj.bean.LifeTestBeanAll@6b26e945
LifeTestBeanAll#@PostConstruct 调用
LifeTestBeanAll#InitializingBean#调用!~
LifeTestBeanAll#@Bean(initMethod) 调用
MyBeanPostProcessor#postProcessAfterInitialization-调用!->beanName=lifeTestBeanAll; bean=com.niewj.bean.LifeTestBeanAll@6b26e945
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
lifeAllConfig
lifeTestBeanAll
myBeanPostProcessor
=============================
LifeTestBeanAll#@PreDestroy 调用
LifeTestBeanAll#Disposable 调用~~
LifeTestBeanAll#@Bean(destroyMethod) 调用

分析整理: 只看 lifeTestBeanAll:

1.BeanPostProcessor#postProcessBeforeInitialization首先调用;

2.@PostConstruct;

3.InitializingBean接口实现;

4.@Bean(initMethod)

5.BeanPostProcessor#postProcessAfterInitialization调用;

6.@PreDestroy

7.Disposable接口实现

8.@Bean(destroyMethod)

初始化顺序: BeanPostProcessor的before-init –> @PostConstruct注解 –> InitializingBean接口 –> @Bean注解指定的initMethod方法 –>BeanPostProcessor的after-init;

destroy的顺序: @PreDestroy注解 –> DisposableBean接口 – > @Bean(destroyMethod)

(2.7) 源码分析:doCreateBean

源码位置:

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
doCreateBean(){...
    try {
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
...
}

1. populateBean: 为bean属性赋值等操作;

2. initializeBean: (下面时序图中的操作)

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
方法流程源码片段:
---方法名:
AbstractAutowireCapableBeanFactory#initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
(1). applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
    1. 遍历并调用BeanPostProcessor#postProcessBeforeInitialization()
(2). invokeInitMethods(beanName, wrappedBean, mbd): 
    1. 调用 InitializingBean接口的 afterPropertiesSet()方法;
    2. 调用 invokeCustomInitMethod() --> @Bean(initMethod) 执行!
(3). applyBeanPostProcessorsAfterInitialization
    1. 调用 postProcessAfterInitialization()
2.1 applyBeanPostProcessorsBeforeInitialization
2.2 invokeInitMethods
2.3. applyBeanPostProcessorsAfterInitialization

时序图:
image.png

(3). BeanPostProcessor扩展

@Autowired注解:

AutowiredAnnotationBeanPostProcessor类–>处理 @Autowired 注解

@PostConstruct && @PreDestroy的实现

InitDestroyAnnotationBeanPostProcessor类实现 @PostConstruct @PreDestroy注解

org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
{
    metadata.invokeInitMethods(bean, beanName);
}

invokeInitMethods:
{
element.invoke(target);
}

根据以上知识点, 便可以知道为什么4个初始化和销毁的方法的优先级顺序是 BeanPostProcessor#before->@PostConstruct->InitializingBean->@Bean(initMethod)->BeanPostProcessor#after了;


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 hi@niewj.com

×

喜欢就点赞,疼爱就打赏