Spring Bean生命周期
传统Bean生命周期
传统的 Java 应用中,Bean 的生命周期很简单,使用 Java 关键字 new 进行 Bean 的实例化后,这个 Bean 就可以使用了。一旦这个 Bean 长期不被使用,Java 自动进行垃圾回收。
Spring Bean生命周期
Spring Bean的生命周期
Spring中Bean的生命周期大致分为5个阶段:
- Bean的实例化
- Bean属性赋值
- Bean的初始化
- Bean的使用
- Bean的销毁
Bean的管理
Spring 根据 Bean 的作用域来选择 Bean 的管理方式:
- 对于 singleton 作用域的 Bean 来说,Spring IoC 容器能够精确地控制 Bean 何时被创建、何时初始化完成以及何时被销毁;
- 对于 prototype 作用域的 Bean 来说,Spring IoC 容器只负责创建,然后就将 Bean 的实例交给客户端代码管理,Spring IoC 容器将不再跟踪其生命周期。
Spring生命周期流程
Spring Bean 的完整生命周期从创建 Spring IoC 容器开始,直到最终 Spring IoC 容器销毁 Bean 为止,其具体流程如下图所示。
自定义Bean的生命周期
在 Spring Bean 生命周期的某个特定时刻,指定一些生命周期回调方法完成一些自定义的操作,对 Bean 的生命周期进行管理。
- 回调方法:
- 初始化回调方法:在 Spring Bean 被初始化后调用,执行一些自定义的回调操作。
- 销毁回调方法:在 Spring Bean 被销毁前调用,执行一些自定义的回调操作。
- 自定义Bean的生命周期回调方法的方式:(按照优先级顺序)
- 通过注解
- 通过接口
- 通过XML配置
1)通过接口实现
可以在 Spring Bean 的 Java 类中,通过实现 InitializingBean(初始化Bean)和 DisposableBean(一次性Bean) 接口,指定 Bean 的生命周期回调方法。
注:一般不建议通过这种方式指定生命周期回调方法,会导致代码的耦合性过高。
回调方式 | 接口 | 方法 | 说明 |
---|---|---|---|
初始化回调 | InitializingBean | afterPropertiesSet() | 指定初始化回调方法,这个方法会在 Spring Bean 被初始化后被调用,执行一些自定义的回调操作。 |
销毁回调 | DisposableBean | destroy() | 指定销毁回调方法,这个方法会在 Spring Bean 被销毁前被调用,执行一些自定义的回调操作。 |
代码示例:
-
Java类
package org.demo6; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; /*** * 使用接口,实现初始化回调 和销毁回调 */ public class LifeCycleBean implements InitializingBean, DisposableBean { private static final Log LOGGER= LogFactory.getLog(LifeCycleBean.class); private String webName; //网站名称 private String url; //网站地址 public void setWebName(String webName) { this.webName = webName; } public void setUrl(String url) { this.url = url; } @Override public String toString() { return "LifeCycleBean{" + "webName='" + webName + '\'' + ", url='" + url + '\'' + '}'; } /** * 初始化回调逻辑 * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { LOGGER.info("调用接口:InitializeingBean,方法:afterPropertiesSet(),无参数"); } /** * 销毁回调逻辑 * @throws Exception */ @Override public void destroy() throws Exception { LOGGER.info("调用接口:DisposableBean,方法:destroy,无参数"); } }
-
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-3.0.xsd"> <!--通过接口自定义生命周期--> <bean id="lifeCycleBean" class="org.demo6.LifeCycleBean"> <property name="webName" value="bdqn"/> <property name="url" value="com.bdqn.www"/> </bean> </beans>
-
main方法
package org.demo6; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { private static final Log LOGGER = LogFactory.getLog(MainApp.class); public static void main(String[] args) { //获取 ClassPathXmlApplicationContext 容器 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo6beans.xml"); LifeCycleBean lifeCycleBean = context.getBean("lifeCycleBean", LifeCycleBean.class); LOGGER.info(lifeCycleBean); //手动销毁 Bean context.close(); } }
-
运行结果
3月 29, 2022 3:49:40 下午 org.demo6.LifeCycleBean afterPropertiesSet 信息: 调用接口:InitializeingBean,方法:afterPropertiesSet(),无参数 3月 29, 2022 3:49:40 下午 org.demo6.MainApp main 信息: LifeCycleBean{webName='bdqn', url='com.bdqn.www'} 3月 29, 2022 3:49:40 下午 org.demo6.LifeCycleBean destroy 信息: 调用接口:DisposableBean,方法:destroy,无参数
2)通过XML配置实现
在 Spring 的 XML 配置中,通过 <bean> 元素中的 init-method (初始化)和 destory-method(销毁)属性,指定 Bean 的生命周期回调方法。
XML 配置属性 | 描述 |
---|---|
init-method | 指定初始化回调方法,这个方法会在 Spring Bean 被初始化后被调用,执行一些自定义的回调操作。 |
destory-method | 指定销毁回调方法,这个方法会在 Spring Bean 被销毁前被调用,执行一些自定义的回调操作。 |
代码示例:
-
Java类
package org.demo6; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * 通过 XML 配置指定生命周期回调方法 */ public class XMLLifeCycleBean { private static final Log LOGGER = LogFactory.getLog(XMLLifeCycleBean.class); //网站名称 private String webName; //网站地址 private String url; public void setWebName(String webName) { this.webName = webName; } public void setUrl(String url) { this.url = url; } @Override public String toString() { return "XMLLifeCycleBean{" + "webName='" + webName + '\'' + ", url='" + url + '\'' + '}'; } /** * 初始化回调方法 */ public void init() { LOGGER.info("在 XML 配置中通过 init-method 属性指定初始化方法:init() 方法"); } /** * 销毁回调方法 */ public void destroy() { LOGGER.info("在 XML 配置中通过 destroy-method 属性指定回调方法:destroy() 方法"); } }
-
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-3.0.xsd"> <!--通过接口自定义生命周期--> <!--<bean id="lifeCycleBean" class="org.demo6.LifeCycleBean"> <property name="webName" value="bdqn"/> <property name="url" value="com.bdqn.www"/> </bean>--> <!--通过XML配置指定生命周期回调方法--> <bean id="xmlLifeCycleBean" class="org.demo6.XMLLifeCycleBean" init-method="init" destroy-method="destroy"> <property name="webName" value="bdqn"/> <property name="url" value="com.bdqn.www"/> </bean> </beans>
-
Main方法
package org.demo6; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 三种方法实现自定义Spring bean生命周期 */ public class MainApp { private static final Log LOGGER = LogFactory.getLog(MainApp.class); public static void main(String[] args) { //获取 ClassPathXmlApplicationContext 容器 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo6beans.xml"); /* * 接口方法 */ /*LifeCycleBean lifeCycleBean = context.getBean("lifeCycleBean", LifeCycleBean.class); LOGGER.info(lifeCycleBean); //手动销毁 Bean context.close();*/ /* *XML配置方法 */ XMLLifeCycleBean xmlbean=context.getBean("xmlLifeCycleBean",XMLLifeCycleBean.class); LOGGER.info(xmlbean); //手动销毁bean context.close(); } }
-
运行结果
3月 29, 2022 4:12:28 下午 org.demo6.XMLLifeCycleBean init 信息: 在 XML 配置中通过 init-method 属性指定初始化方法:init() 方法 3月 29, 2022 4:12:28 下午 org.demo6.MainApp main 信息: XMLLifeCycleBean{webName='bdqn', url='com.bdqn.www'} 3月 29, 2022 4:12:28 下午 org.demo6.XMLLifeCycleBean destroy 信息: 在 XML 配置中通过 destroy-method 属性指定回调方法:destroy() 方法
3)通过注解实现
可以通过JSR-250的@PostConstruct和@PreDestroy注解,指定Bean的生命周期回调方法.
注解 | 描述 |
---|---|
@PostConstruct | 指定初始化回调方法,这个方法会在 Spring Bean 被初始化后被调用,执行一些自定义的回调操作。 |
@PreDestroy | 指定销毁回调方法,这个方法会在 Spring Bean 被销毁前被调用,执行一些自定义的回调操作。 |
代码示例:
-
java类
package org.demo6; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * 注释生命周期类 */ public class AnnotationLifeCycleBean { private static final Log LOGGER = LogFactory.getLog(AnnotationLifeCycleBean.class); //网站名称 private String webName; //网站地址 private String url; public AnnotationLifeCycleBean(String webName, String url) { this.webName = webName; this.url = url; } @Override public String toString() { return "AnnotationLifeCycleBean{" + "webName='" + webName + '\'' + ", url='" + url + '\'' + '}'; } /** * 初始化回调方法 */ @PostConstruct public void init(){ LOGGER.info("通过@PostConstrust注解,指定初始化方法,init()方法"); } /** * 销毁回调方法 */ @PreDestroy public void destroy(){ LOGGER.info("通过@PreDestroy注解,指定初始化方法,destroy()方法"); } }
-
配置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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!--通过接口自定义生命周期--> <!--<bean id="lifeCycleBean" class="org.demo6.LifeCycleBean"> <property name="webName" value="bdqn"/> <property name="url" value="com.bdqn.www"/> </bean>--> <!--通过XML配置指定生命周期回调方法--> <!-- <bean id="xmlLifeCycleBean" class="org.demo6.XMLLifeCycleBean" init-method="init" destroy-method="destroy"> <property name="webName" value="bdqn"/> <property name="url" value="com.bdqn.www"/> </bean> --> <!--扫描组件--> <context:component-scan base-package="org.demo6"/> <!--通过注解指定Bean生命周期回调方法--> <bean id="annotationLifeCycleBean" class="org.demo6.AnnotationLifeCycleBean"> <constructor-arg name="webName" value="bdqn"/> <constructor-arg name="url" value="com.bdqn.www"/> </bean> </beans>
-
main方法
package org.demo6; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 三种方法实现自定义Spring bean生命周期 */ public class MainApp { private static final Log LOGGER = LogFactory.getLog(MainApp.class); public static void main(String[] args) { //获取 ClassPathXmlApplicationContext 容器 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo6beans.xml"); /* * 接口方法 */ /*LifeCycleBean lifeCycleBean = context.getBean("lifeCycleBean", LifeCycleBean.class); LOGGER.info(lifeCycleBean); */ /* *XML配置方法 */ /*XMLLifeCycleBean xmlbean=context.getBean("xmlLifeCycleBean",XMLLifeCycleBean.class); LOGGER.info(xmlbean);*/ /** * 注解配置方法 */ AnnotationLifeCycleBean annotationLifeCycleBean=context.getBean("annotationLifeCycleBean",AnnotationLifeCycleBean.class); LOGGER.info(annotationLifeCycleBean); /*System.out.println(annotationLifeCycleBean.toString());*/ //手动销毁bean context.close(); } }
-
运行结果
16:24:31.394 [main] INFO org.demo6.AnnotationLifeCycleBean - 通过@PostConstrust注解,指定初始化方法,init()方法 AnnotationLifeCycleBean{webName='bdqn', url='com.bdqn.www'} 16:24:31.426 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@4cf4d528, started on Wed Mar 30 16:24:30 CST 2022 16:24:31.427 [main] INFO org.demo6.AnnotationLifeCycleBean - 通过@PreDestroy注解,指定初始化方法,destroy()方法
![](https://res.hc-cdn.com/ecology/9.3.130/v2_resources\images\global\blog-dialog.png)
华为开发者空间发布
让每位开发者拥有一台云主机
- 点赞
- 收藏
- 关注作者
评论(0)