9.2 自定义 Bean 的生命周期
我们可以在 Spring Bean 生命周期的某个特定时刻,指定一些生命周期回调方法完成一些自定义的操作,对 Bean 的生命周期进行管理。
Bean 的生命周期回调方法主要有两种:
- 初始化回调方法:在 Spring Bean 被初始化后调用,执行一些自定义的回调操作。
- 销毁回调方法:在 Spring Bean 被销毁前调用,执行一些自定义的回调操作。
我们可以通过以下 3 种方式自定义 Bean 的生命周期回调方法:
- 通过接口实现
- 通过 XML 配置实现
- 使用注解实现
如果一个 Bean 中有多种生命周期回调方法时,优先级顺序为:注解 > 接口 > XML 配置。
1. 通过接口实现
我们可以在 Spring Bean 的 Java 类中,通过实现 InitializingBean 和 DisposableBean 接口,指定 Bean 的生命周期回调方法。
回调方式 | 接口 | 方法 | 说明 |
初始化回调 | InitializingBean | afterPropertiesSet() | 指定初始化回调方法,这个方法会在 Spring Bean 被初始化后被调用,执行一些自定义的回调操作。 |
销毁回调 | DisposableBean | destroy() | 指定销毁回调方法,这个方法会在 Spring Bean 被销毁前被调用,执行一些自定义的回调操作。 |
注意:通常情况下,我们不建议通过这种方式指定生命周期回调方法,这是由于这种方式会导致代码的耦合性过高。
例 1
下面我们就通过一个实例,来演示下如何通过接口指定 Bean 的生命周期回调方法。
创建命名为 LifeCycleBean 的类,代码如下:
package section2.demo1;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* ClassName: LifeCycleBean
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class LifeCycleBean implements InitializingBean, DisposableBean {
private static final Log LOGGER = LogFactory.getLog(LifeCycleBean.class);
// 网站名称
private String site;
// 网站地址
private String url;
public void setSite(String site) {
this.site = site;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "LifeCycleBean{" +
"site='" + site + '\'' +
", url='" + url + '\'' +
'}';
}
/**
* 初始化回调逻辑
*
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
LOGGER.info(" 调用接口:InitializingBean,方法:afterPropertiesSet,无参数");
}
/**
* 销毁回调逻辑
*
* @throws Exception
*/
@Override
public void destroy() throws Exception {
LOGGER.info(" 调用接口:DisposableBean,方法:destroy,无参数");
}
}
修改 Spring 配置文件 spring-config.xml,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="lifeCycleBean" class="section2.demo1.LifeCycleBean">
<property name="site" value="传陆编程"/>
<property name="url" value="http://localhost"/>
</bean>
</beans>
创建命名为 MainApp 的类,代码如下:
package section2.demo1;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* ClassName: MainApp
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class MainApp {
private static final Log LOGGER = LogFactory.getLog(MainApp.class);
public static void main(String[] args) {
//获取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
LifeCycleBean lifeCycleBean = context.getBean("lifeCycleBean", LifeCycleBean.class);
LOGGER.info(lifeCycleBean);
//手动销毁 Bean
context.close();
}
}
执行 MainApp 中的 main 方法,控制台输出如下:
4月 08, 2022 1:04:15 下午 section2.demo1.LifeCycleBean afterPropertiesSet
信息: 调用接口:InitializingBean,方法:afterPropertiesSet,无参数
4月 08, 2022 1:04:15 下午 section2.demo1.MainApp main
信息: LifeCycleBean{site='传陆编程', url='http://localhost'}
4月 08, 2022 1:04:15 下午 section2.demo1.LifeCycleBean destroy
信息: 调用接口:DisposableBean,方法:destroy,无参数
2. 通过 XML 配置实现
我们还可以在 Spring 的 XML 配置中,通过 <bean>
元素中的 init-method
和 destory-method
XML 配置属性 | 描述 |
init-method | 指定初始化回调方法,这个方法会在 Spring Bean 被初始化后被调用,执行一些自定义的回调操作。 |
destory-method | 指定销毁回调方法,这个方法会在 Spring Bean 被销毁前被调用,执行一些自定义的回调操作。 |
例 2
下面我们通过一个实例,演示下如何通过 XML 配置指定 Bean 的生命周期回调方法。
创建命名为 XMLLifeCycleBean 的 Java 类,代码如下:
package section2.demo2;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* ClassName: XMLLifeCycleBean
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class XMLLifeCycleBean {
private static final Log LOGGER = LogFactory.getLog(XMLLifeCycleBean.class);
// 网站名称
private String site;
// 网站地址
private String url;
public void setSite(String site) {
this.site = site;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "XMLLifeCycleBean{" +
"site='" + site + '\'' +
", url='" + url + '\'' +
'}';
}
/**
* 初始化回调方法
*/
public void init() {
LOGGER.info("在 XML 配置中通过 init-method 属性指定初始化方法:init() 方法");
}
/**
* 销毁回调方法
*/
public void destroy() {
LOGGER.info("在 XML 配置中通过 destroy-method 属性指定回调方法:destroy() 方法");
}
}
修改 Spring 配置文件 spring-config.xml,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过 XML 配置指定生命周期回调方法-->
<bean id="xmlLifeCycleBean" class="section2.demo2.XMLLifeCycleBean" init-method="init" destroy-method="destroy">
<property name="site" value="传陆编程"/>
<property name="url" value="http://localhost"/>
</bean>
</beans>
创建命名为 MainApp 的类,代码如下:
package section2.demo2;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* ClassName: MainApp
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class MainApp {
private static final Log LOGGER = LogFactory.getLog(MainApp.class);
public static void main(String[] args) {
//获取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
XMLLifeCycleBean xmlLifeCycleBean = context.getBean("xmlLifeCycleBean", XMLLifeCycleBean.class);
LOGGER.info(xmlLifeCycleBean);
//手动销毁 Bean
context.close();
}
}
执行 MainApp 中的 main 方法,控制台输出如下:
4月 07, 2022 7:53:18 下午 section3.demo2.XMLLifeCycleBean init
信息: 在 XML 配置中通过 init-method 属性指定初始化方法:init() 方法
4月 07, 2022 7:53:18 下午 section3.demo2.MainApp main
信息: XMLLifeCycleBean{site='传陆编程', url='http://localhost'}
4月 07, 2022 7:53:18 下午 section3.demo2.XMLLifeCycleBean destroy
信息: 在 XML 配置中通过 destroy-method 属性指定回调方法:destroy() 方法
3. 使用注解实现
我们还可以通过 JSR-250 的 @PostConstruct
和 @PreDestroy
注解 | 描述 |
@PostConstruct | 指定初始化回调方法,这个方法会在 Spring Bean 被初始化后被调用,执行一些自定义的回调操作。 |
@PreDestroy | 指定销毁回调方法,这个方法会在 Spring Bean 被销毁前被调用,执行一些自定义的回调操作。 |
例 3
下面我们通过一个实例,演示下如何通过注解指定 Bean 的生命周期回调方法。
创建命名为 AnnotationLifeCycleBean 的 Java 类,代码如下:
package section2.demo3;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* ClassName: AnnotationLifeCycleBean
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class AnnotationLifeCycleBean {
private static final Log LOGGER = LogFactory.getLog(AnnotationLifeCycleBean.class);
// 网站名称
private String site;
// 网站地址
private String url;
public void setSite(String site) {
this.site = site;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "XMLLifeCycleBean{" +
"site='" + site + '\'' +
", url='" + url + '\'' +
'}';
}
/**
* 初始化回调方法
*/
@PostConstruct
public void init() {
LOGGER.info("通过注解 @PostConstruct 调用指定初始化回调方法:init() 方法");
}
/**
* 销毁回调方法
*/
@PreDestroy
public void destroy() {
LOGGER.info("通过注解 @PreDestroy 调用指定销毁回调方法:destroy() 方法");
}
}
修改 Spring 配置文件 spring-config.xml,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--注解扫描-->
<context:component-scan base-package="section3.demo3"/>
<!--通过注解指定生命周期回调方法-->
<bean id="annotationLifeCycleBean" class="section3.demo3.AnnotationLifeCycleBean">
<property name="site" value="传陆编程"/>
<property name="url" value="http://localhost"/>
</bean>
</beans>
创建命名为 MainApp 的类,代码如下:
package section2.demo3;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* ClassName: MainApp
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class MainApp {
private static final Log LOGGER = LogFactory.getLog(MainApp.class);
public static void main(String[] args) {
//获取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
AnnotationLifeCycleBean annotationLifeCycleBean = context.getBean("annotationLifeCycleBean", AnnotationLifeCycleBean.class);
LOGGER.info(annotationLifeCycleBean);
//手动销毁 Bean
context.close();
}
}
执行 MainApp 中的 main 方法,控制台输出如下:
4月 08, 2022 1:30:06 下午 section2.demo3.AnnotationLifeCycleBean init
信息: 通过注解 @PostConstruct 调用指定初始化回调方法:init() 方法
4月 08, 2022 1:30:06 下午 section2.demo3.MainApp main
信息: XMLLifeCycleBean{site='传陆编程', url='http://localhost'}
4月 08, 2022 1:30:06 下午 section2.demo3.AnnotationLifeCycleBean destroy
信息: 通过注解 @PreDestroy 调用指定销毁回调方法:destroy() 方法
注意:这里需要依赖 jsr250-api-1.0.jar 这个 jar 包,本课程已经把它放在了 Spring-5.3.18 目录里