Bean的生命周期

  • Bean的生命周期图示如下:
  • 文字描述如下:
    • Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化。
    • Bean实例化后对将Bean的引入和值注入到Bean的属性中。
    • 如果Bean实现了BeanNameAware接口,Spring将Bean的Id传递给setBeanName()方法。
    • 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入。
    • 如果Bean实现了ApplicationContextAware接口,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
    • 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
    • 如果Bean使用了@PostConstruct注解进行初始化,则会调用该注解标注的方法;如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()方法;如果bean使用init-method声明了初始化方法,该方法也会被调用。
    • 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
    • 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
    • 如果Bean使用了@PreDestroy注解进行销毁,则会调用此注解标注的销毁方法;如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法;如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

参考:https://www.cnblogs.com/javazhiyin/p/10905294.html

  • 测试Bean的生命周期:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class MyBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

private ApplicationContext applicationContext;

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

public void setBeanName(String name) {
System.out.println("调用BeanNameAware的setBeanName()方法");
}

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware的setBeanFactory()方法");
}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
System.out.println("调用ApplicationContextAware的setApplicationContext方法");
}

public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean的afterPropertiesSet()方法");
}

public void myInit() {
System.out.println("调用init-method属性配置的初始化方法");
}

public void myDestroy() {
System.out.println("调用destroy-method属性配置的初始化方法,销毁bean");
}

public void destroy() throws Exception {
System.out.println("调用DisposableBean的destroy()方法");
}

@PostConstruct
public void annotationInit(){
System.out.println("调用@PostConstruct注解的初始化方法");
}

@PreDestroy
public void annotationDestroy(){
System.out.println("调用@PreDestroy注解的销毁方法");
}
}

public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用BeanPostProcessor的postProcessBeforeInitialization方法");
return bean;
}

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用BeanPostProcessor的postProcessAfterInitialization方法");
return bean;
}
}

@Configuration
public class MainConfig {
@Bean(initMethod="myInit",destroyMethod="myDestroy")
public MyBean myBean() {
return new MyBean();
}

@Bean
public MyBeanPostProcessor myBeanPostProcessor(){
return new MyBeanPostProcessor();
}
}

public class MainTest {
public static void main(String[] args) {
System.out.println("------提示:现在开始初始化容器------");
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("------提示:容器初始化成功------");
MyBean bean = applicationContext.getBean(MyBean.class);
System.out.println("------输出bean:" + bean + "------");
System.out.println("------提示:现在开始关闭容器------");
applicationContext.close();
}
}

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
------提示:现在开始初始化容器------
十一月 29, 2020 11:42:43 上午 org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker postProcessAfterInitialization
信息: Bean 'mainConfig' of type [com.example.config.MainConfig$$EnhancerBySpringCGLIB$$442084fc] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
MyBean实例化
调用BeanNameAware的setBeanName()方法
调用BeanFactoryAware的setBeanFactory()方法
调用ApplicationContextAware的setApplicationContext方法
调用BeanPostProcessor的postProcessBeforeInitialization方法
调用@PostConstruct注解的初始化方法
调用InitializingBean的afterPropertiesSet()方法
调用init-method属性配置的初始化方法
调用BeanPostProcessor的postProcessAfterInitialization方法
------提示:容器初始化成功------
------输出bean:com.example.bean.MyBean@57175e74------
------提示:现在开始关闭容器------
调用@PreDestroy注解的销毁方法
调用DisposableBean的destroy()方法
调用destroy-method属性配置的初始化方法,销毁bean
  • 其中,指定初始化和销毁方法的几种方式:

    • ①通过@Bean指定init-method和destroy-method。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class Car {
    public Car(){
    System.out.println("car constructor...");
    }

    public void init(){
    System.out.println("car ... init...");
    }

    public void destroy(){
    System.out.println("car ... destroy...");
    }
    }

    @Configuration
    public class MainConfig {
    @Bean(initMethod="init",destroyMethod="destroy")
    public Car car() {
    return new Car();
    }
    }

    public class MainTest {
    public static void main(String[] args) {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("容器初始化完成");
    //关闭容器
    applicationContext.close();
    //打印如下:
    //car constructor...
    //car ... init...
    //容器初始化完成
    //car ... destroy...
    }
    }
    • ②通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class Car implements InitializingBean, DisposableBean {
    public Car(){
    System.out.println("car constructor...");
    }

    public void destroy() throws Exception {
    System.out.println("car...destroy...");
    }

    public void afterPropertiesSet() throws Exception {
    System.out.println("car...afterPropertiesSet...");
    }
    }

    @Configuration
    public class MainConfig {
    @Bean
    public Car car() {
    return new Car();
    }
    }

    public class MainTest {
    public static void main(String[] args) {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("容器初始化完成");
    //关闭容器
    applicationContext.close();
    //打印如下:
    //car constructor...
    //car...afterPropertiesSet...
    //容器初始化完成
    //car...destroy...
    }
    }
    • ③使用@PostConstruct: 在bean创建完成并且属性赋值完成后来执行初始化方法;@PreDestroy: 在容器销毁bean之前通知我们进行清理工作。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public class Car {
    public Car(){
    System.out.println("car constructor...");
    }

    //对象创建并赋值之后调用
    @PostConstruct
    public void init(){
    System.out.println("car....@PostConstruct...");
    }

    //容器移除对象之前
    @PreDestroy
    public void destroy(){
    System.out.println("car....@PreDestroy...");
    }
    }

    @Configuration
    public class MainConfig {
    @Bean
    public Car car() {
    return new Car();
    }
    }

    public class MainTest {
    public static void main(String[] args) {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("容器初始化完成");
    //关闭容器
    applicationContext.close();
    //打印如下:
    //car constructor...
    //car....@PostConstruct...
    //容器初始化完成
    //car....@PreDestroy...
    }
    }
  • Spring底层几个后置处理器的作用:

    • ApplicationContextAwareProcessor是BeanPostProcessor(后置处理器)的一个实现类,其作用是如果bean对象的类是ApplicationContextAware类型,则会执行setApplicationContext方法将IOC容器赋值给此bean对象。上述例子的MyBean即实现了ApplicationContextAware接口从而得到IOC容器:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;


    /**
    * Create a new ApplicationContextAwareProcessor for the given context.
    */
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
    this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }


    @Override
    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
    bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
    bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
    return bean;
    }

    AccessControlContext acc = null;

    if (System.getSecurityManager() != null) {
    acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    }

    if (acc != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    invokeAwareInterfaces(bean);
    return null;
    }, acc);
    }
    else {
    invokeAwareInterfaces(bean);
    }

    return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
    ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) {
    ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }
    if (bean instanceof ResourceLoaderAware) {
    ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }
    if (bean instanceof ApplicationEventPublisherAware) {
    ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    }
    if (bean instanceof MessageSourceAware) {
    ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }
    //给bean赋值IOC容器
    if (bean instanceof ApplicationContextAware) {
    ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
    }

    }
    • InitDestroyAnnotationBeanPostProcessor 也是 BeanPostProcessors 的一个实现类,其对 BeanPostProcessor 的实现是通过同时实现 DestructionAwareBeanPostProcessor 和 MergedBeanDefinitionPostProcessor 这两个接口来完成的,其允许使用注解替代 Spring 的 InitializingBean 和 DisposableBean 回调接口,上述的第③种初始化方法的**@PostConstruct** 和 @PreDestroy 注解发挥作用就是由其实现的。核心源码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // 调用方法获取生命周期元数据并保存
    LifecycleMetadata metadata = findLifecycleMetadata(beanType);
    // 验证相关方法
    metadata.checkConfigMembers(beanDefinition);
    }

    private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
    if (this.lifecycleMetadataCache == null) {
    // 在 Bean 销毁过程中反序列化后调用
    // Happens after deserialization, during destruction...
    return buildLifecycleMetadata(clazz);
    }
    // Quick check on the concurrent map first, with minimal locking.
    // 首先尝试从缓存中获取元数据
    LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
    //如果从缓存中获取失败则尝试加锁创建元数据
    if (metadata == null) {
    synchronized (this.lifecycleMetadataCache) {
    metadata = this.lifecycleMetadataCache.get(clazz);
    if (metadata == null) {
    //构建生命周期元数据,也就是解析带 @PostConstruct 和 @PreDestroy 注解的方法。
    metadata = buildLifecycleMetadata(clazz);
    this.lifecycleMetadataCache.put(clazz, metadata);
    }
    return metadata;
    }
    }
    return metadata;
    }

    private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
    if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
    return this.emptyLifecycleMetadata;
    }
    // 实例化后的回调方法(@PostConstruct)
    List<LifecycleElement> initMethods = new ArrayList<>();
    // 销毁前的回调方法(@PreDestroy)
    List<LifecycleElement> destroyMethods = new ArrayList<>();
    // 获取正在处理的目标类
    Class<?> targetClass = clazz;

    do {
    // 下面两个列表是为了保存每一轮循环搜索到的相关方法(因为可能存在父类)
    final List<LifecycleElement> currInitMethods = new ArrayList<>();
    final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

    ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    // 当前方法的注解中包含 initAnnotationType 注解时(此时就是 @PostConstruct)
    if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
    LifecycleElement element = new LifecycleElement(method);
    currInitMethods.add(element);
    if (logger.isTraceEnabled()) {
    logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
    }
    }
    // 当前方法的注解中包含 destroyAnnotationType 注解时(此时就是 @PreDestroy)
    if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
    // 创建一个元数据元素(当前方法的包装类)并添加到集合中
    currDestroyMethods.add(new LifecycleElement(method));
    if (logger.isTraceEnabled()) {
    logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
    }
    }
    });
    //将本次循环中获取到的对应方法集合(currInitMethods 和 currDestroyMethods)保存到总集合(initMethods 和 destroyMethods)中
    initMethods.addAll(0, currInitMethods);
    destroyMethods.addAll(currDestroyMethods);
    // 获取当前类的父类
    targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
    new LifecycleMetadata(clazz, initMethods, destroyMethods));
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 尝试从缓存中获取元数据
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
    // 通过元数据 LifecycleMetadata 中的 invokeInitMethods 方法调用初始化方法(@PostConstruct)
    metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
    throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
    throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
    }

    而销毁前调用**@PreDestroy**标注的方法的实现在DisposableBeanAdapter的destroy()方法中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void destroy() {
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
    for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
    // 当这里的processor为CommonAnnotationBeanPostProcessor 时调用 @PreDestroy方法,因为CommonAnnotationBeanPostProcessor中未实现postProcessBeforeDestruction方法,因此直接调用其父类 InitDestroyAnnotationBeanPostProcessor 中的 postProcessBeforeDestruction 方法
    processor.postProcessBeforeDestruction(this.bean, this.beanName);
    }
    }
    ...
    }