spring注解开发2——bean的生命周期

本文最后更新于:2022年5月12日 凌晨

摘要:介绍了bean的生命周期以及执行时机、如何指定bean各个生命周期执行的方法。

Bean的生命周期基础

bean生命周期是指bean从创建——>初始化——>销毁的过程。容器管理bean的生命周期:自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候,调用自定义的初始化和销毁方法。

构造(对象创建)

  • 单实例:容器创建的时候创建对象

  • 多实例:每次获取的时候创建对象

初始化:

  •  对象创建完成,并赋值好,调用初始化方法
    

销毁:

  •  单实例:容器关闭的时候调用销毁方法
    
  •  多实例:容器不会管理这个bean;容器不会调用销毁方法
    

指定初始化和销毁方法

通过@Bean指定指定init-method 和 destroy-method

  1. 创建一个Phone类,并在里面定义初始化和销毁方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.shg.bean;

/**
* @author: shg
* @create: 2022-05-11 12:19 上午
*/
public class Phone {
public Phone() {
System.out.println("phone constructor ...");
}

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

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

  1. 在配置类中,通过@Bean注解的参数initMethod和destroyMethod指定初始化和销毁方法
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
package com.shg.config;

/**
* @author: shg
* @create: 2022-05-11 12:22 上午
*/

import com.shg.bean.Phone;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* 1)指定初始化和销毁方法:
* 通过@Bean指定指定init-method 和 destroy-method
*/
@Configuration
public class MyConfig1 {

@Bean(initMethod = "init", destroyMethod = "destroy")
public Phone phone() {
return new Phone();
}
}

  1. 创建一个测试类,查看结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.shg.test;

import com.shg.config.MyConfig1;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @author: shg
* @create: 2022-05-11 2:03 下午
*/

public class LifeCycleTest {

@Test
public void test01() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig1.class);
context.close();

}
}

输出结果如下:

1
2
3
phone constructor ...
phone init ...
phone destroy ...

实现InitializingBean和DisposableBean接口

通过在让注册的Bean实现InitializingBean接口中的afterPropertiesSet方法和DisposableBean接口destroy方法

  1. 定义一个Computer类,分别实现InitializingBean和DisposableBean接口
  • InitializingBean#afterPropertiesSet():定义初始化逻辑
  • DisposableBean#destroy():定义销毁逻辑
  • 后续在配置类中使用@ComponentScan扫描组件的方式将组件注册到容器中,所以给该类加上@Component注解
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
package com.shg.bean;

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

/**
* @author: shg
* @create: 2022-05-11 2:23 下午
*/
@Component
public class Computer implements InitializingBean, DisposableBean {

public Computer() {
System.out.println("Computer.Computer");
}

@Override
public void destroy() throws Exception {
System.out.println("Computer.destroy");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Computer.afterPropertiesSet");
}
}

  1. 在配置类中通过@CompnentScan注解将Computer类(使用了@Component注解)注册到容器中
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
package com.shg.config;

/**
* @author: shg
* @create: 2022-05-11 12:22 上午
*/

import com.shg.bean.Phone;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* 1)指定初始化和销毁方法:
* 通过@Bean指定指定init-method 和 destroy-method
* 2)通过让Bean实现InitializingBean(定义初始化逻辑)、
* DisposableBean(定义销毁逻辑)
*/
@Configuration
@ComponentScan("com.shg.bean")
public class MyConfig1 {

@Bean(initMethod = "init", destroyMethod = "destroy")
public Phone phone() {
return new Phone();
}
}

  1. 查看结果
1
2
3
4
5
@Test
public void test01() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig1.class);
context.close();
}
1
2
3
4
5
6
Computer.Computer
Computer.afterPropertiesSet
phone constructor ...
phone init ...
phone destroy ...
Computer.destroy

使用JSR250规范中的注解

分别在初始化方法上加@PostConstruct、在销毁方法上加@PreDestroy,当容器在bean执行到对应生命周期会调用对应方法

  1. 定义一个Pad类,并在其初始化和销毁方法上加上注解
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
package com.shg.bean;

import org.springframework.stereotype.Component;

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

/**
* @author: shg
* @create: 2022-05-11 2:58 下午
*/
@Component
public class Pad {
public Pad() {
System.out.println("Pad.Pad");
}

@PostConstruct
public void init() {
System.out.println("Pad.init");
}

@PreDestroy
public void destroy() {
System.out.println("Pad.destroy");
}
}

  1. 配置类同上,无需改动

  2. 查看输出结果(代码无需改动)

1
2
3
4
5
6
7
8
9
Computer.Computer
Computer.afterPropertiesSet
Pad.Pad
Pad.init
phone constructor ...
phone init ...
phone destroy ...
Pad.destroy
Computer.destroy

BeanPostProcessor:bean的后置处理器

容器中有BeanPostProcessor接口的实现类,容器所管理的bean在初始化前后进行一些处理工作,在初始化之前会调用接口中的postProcessBeforeInitialization方法,在初始化之后会调用接口中的postProcessAfterInitialization方法。

  1. 定义BeanPostProcessor接口的实现类,并在类上加上@Component注解
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
package com.shg.processor;

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

/**
* @author: shg
* @create: 2022-05-11 3:20 下午
*/

/**
* 后置处理器:初始化前后进行处理工作
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
return bean;
}

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

  1. 修改配置类

将类上面的注解@ComponentScan(“com.shg.bean”)修改为:@ComponentScan({“com.shg.bean”, “com.shg.processor”})

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
package com.shg.config;

/**
* @author: shg
* @create: 2022-05-11 12:22 上午
*/

import com.shg.bean.Phone;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* 1)指定初始化和销毁方法:
* 通过@Bean指定指定init-method 和 destroy-method
* 2)通过让Bean实现InitializingBean(定义初始化逻辑)、
* DisposableBean(定义销毁逻辑)
* 3)使用JSR250规范中的注解
* 在初始化方法上加@PostConstruct
* 在销毁方法上加@PreDestroy
* 4)BeanPostProcessor:bean的后置处理器
* 在bean初始化前后进行一些处理工作
* postProcessBeforeInitialization:在初始化之前执行
* postProcessAfterInitialization:在初始化之后执行
*/
@Configuration
@ComponentScan({"com.shg.bean", "com.shg.processor"})
public class MyConfig1 {

@Bean(initMethod = "init", destroyMethod = "destroy")
public Phone phone() {
return new Phone();
}
}

  1. 查看输出结果

每个bean在构造方法之后、初始化方法之前会调用postProcessBeforeInitialization

在初始化方法之后、销毁方法之前会调用:postProcessAfterInitialization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
MyBeanPostProcessor.postProcessBeforeInitialization
MyBeanPostProcessor.postProcessAfterInitialization
Computer.Computer
MyBeanPostProcessor.postProcessBeforeInitialization
Computer.afterPropertiesSet
MyBeanPostProcessor.postProcessAfterInitialization
Pad.Pad
MyBeanPostProcessor.postProcessBeforeInitialization
Pad.init
MyBeanPostProcessor.postProcessAfterInitialization
phone constructor ...
MyBeanPostProcessor.postProcessBeforeInitialization
phone init ...
MyBeanPostProcessor.postProcessAfterInitialization
phone destroy ...
Pad.destroy
Computer.destroy

总结

bean的生命周期共分为:bean创建、初始化、销毁三个阶段。定义bean的初始化和销毁方法主要有:通过@Bean注解的init-method 和 destroy-method来指定、实现InitializingBean和DisposableBean接口中的对应方法、使用JSR250规范中的@PostConstructh和@PreDestroy注解。此外,如果容器中有BeanPostProcessor接口的实现类,在初始化方法执行的前后还会执行该接口中的postProcessBeforeInitialization和postProcessAfterInitialization方法。


spring注解开发2——bean的生命周期
https://shgang97.github.io/posts/spring-annotation-2-ac361e9c95dc/
作者
shgang
发布于
2022年5月10日
更新于
2022年5月12日
许可协议