Spring框架中bean的前置处理和后置处理

Spring框架中Bean的创建过程如下:

Aware interfaces Callbacks in Bean Lifecycle

其中BeanPostProcessor接口包含两个执行过程,分别是在bean执行init方法之前和执行init方法之后执行。代码如下:

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
@Configuration
public class MyBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("我在bean初始化前执行");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("我在bean初始化之后执行");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}

@Bean(name = "DBConnection", initMethod = "init", destroyMethod = "destroy")
public DatabaseConfig mysqlConnection() {
Properties properties = System.getProperties();
String url = properties.getProperty("url");
String driverName = properties.getProperty("driverName");
String userName = properties.getProperty("userName");
String password = properties.getProperty("password");
return new DatabaseConfig(driverName, url, userName, password);
}

}

上述代码新建了自定义的MyBeanPostProcessor,并实现了接口BeanPostProcessor中的两个接口(自带default方法),同时,还定义了一个名为DBConnection的bean,指定了初始化方法和销毁前执行的方法。

其中,DatabaseConfig的定义如下:

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
@Data
public class DatabaseConfig {

private static Connection connection;

private String driverName;
private String url;
private String userName;
private String password;

public DatabaseConfig(String driverName, String url, String userName, String password) {
this.driverName = driverName;
this.url = url;
this.userName = userName;
this.password = password;
System.out.println("构造连接参数...");
}
public void init() {
System.out.println("初始化数据库连接");
}
public void destroy() {
System.out.println("销毁数据库连接");
}
}

为了方便识别执行阶段,分别在构造器和init以及destroy方法中加入了文字说明。

最后的执行结果如下:

1
2
3
4
5
6
构造连接参数...
我在bean初始化前执行
初始化数据库连接
我在bean初始化之后执行
...
销毁数据库连接

由此可见,构造器内的代码是最先执行的,属于填充属性阶段(即Populate properties),接着执行MyBeanPostProcessor#postProcessBeforeInitialization方法,然后执行init方法,之后执行MyBeanPostProcessor#postProcessBeforeInitialization,最后在关闭应用时执行destroy方法。

Spring框架中bean的生命周期

使用@PostConstruct@PreDestroy注解在同一个配置类中执行bean的初始化前和销毁前的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
public class MyBeanPostProcessor {
@Bean
public String helloWorld() {
return "hello world";
}

@PostConstruct
public void init() {
System.out.println("我是初始化前执行的方法");
}

@PreDestroy
public void destroy() {
System.out.println("我是销毁前执行的方法");
}
}

上面的配置类中只定义了一个bean,且是字符串类型(方便举例),大部分情况下应该是返回一个对象。

使用@Bean(initMethod = "init", destroyMethod = "destroy")注解执行bean初始化前和销毁前的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
public class ConfigTest {
@Bean(initMethod = "init", destroyMethod = "destroy")
Test1 test1() {
return new Test1(); // 使用默认的无参构造器
}
}
// 定义Bean的内容,本质上是一个普通的java类
public class Test1 {
// 初始化前的执行方法
public void init() {
System.out.println("this is init method");
}
// 销毁前的执行方法
public void destroy() {
System.out.println("this is destroy method");
}
}