9 生命周期回调方法
对于Spring bean
来讲,我们默认可以指定两个生命周期回调方法。一个是在ApplicationContext
将bean
初始化,包括注入对应的依赖后的回调方法;另一个是在ApplicationContext
准备销毁之前的回调方法。要实现这种回调主要有三种方式:实现特定的接口、在XML
配置文件中指定回调方法和使用JSR-250
标准的注解。
9.1 实现特定接口
针对bean
初始化后的回调和ApplicationContext
销毁前的回调,Spring
分别为我们了提供了InitializingBean
和DisposableBean
接口供用户实现,这样Spring
在需要进行回调时就会调用对应接口提供的回调方法。
9.1.1 InitializingBean
InitializingBean
是用来定义ApplicationContext
在完全初始化一个bean
以后需要需要回调的方法的,其中只定义了一个afterPropertiesSet()
方法。如其名称所描述的那样,该方法将在ApplicationContext
将一个bean
完全初始化,包括将对应的依赖项都注入以后才会被调用。InitializingBean
的完全定义如下。
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
由于InitializingBean
的afterPropertiesSet()
方法会在依赖项都进行注入以后再回调,所以该方法通常会用来检查必要的依赖注入,以使我们能够在bean
被初始化时就发现其中的错误,而不是在很长时间使用以后才发现。如果你去看Spring
的源码,你就会发现源码中有很多InitializingBean
的使用,而且基本都是用来检查必要的依赖项是否为空的。
public class Hello implements InitializingBean {
private World world;
/**
* 该方法将在当前bean被完全初始化后被调用
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(world, "world should not be null.");
}
public void setWorld(World world) {
this.world = world;
}
}
9.1.2 DisposableBean
DisposableBean
是用来定义在ApplicationContext
销毁之前需要回调的方法的。DisposableBean
接口中只定义了一个destroy()
方法,在ApplicationContext
被销毁前,Spring
将依次调用bean
容器中实现了DisposableBean
接口的destroy()
方法。所以,我们可以通过实现该接口的destroy()
方法来达到在ApplicationContext
销毁前释放某些特定资源的目的。
public interface DisposableBean {
void destroy() throws Exception;
}
在Spring
的源码中,也有很多实现了DisposableBean
接口的类,如我们熟悉的ApplicationContext
实现类、SingleConnectionDataSource
等。
9.2 在XML中配置回调方法
在XML
配置文件中通过bean
元素定义一个bean
时,我们可以通过bean元素的init-method
属性和destroy-method
属性来指定当前bean在初始化以后和ApplicationContext
销毁前的回调方法。需要注意的是所指定的回调方法必须是没有参数的。
通过init-method
属性来指定初始化方法时所对应的方法必须是该bean中所拥有的方法,所以首先我们需要在对应的bean中定义对应的初始化方法,这里假设我们需要在bean中定义一个init()
方法作为该bean的初始化方法,那么我们可以对我们的bean进行类似如下定义。
public class Hello {
private World world;
/**
* 该方法将被用来作为初始化方法,在当前bean被完全初始化后被调用
*/
public void init() {
Assert.notNull(world, "world should not be null.");
}
public void setWorld(World world) {
this.world = world;
}
}
接下来就是在XML配置文件中定义该bean时通过init-method
属性定义对应的初始化方法为init()
方法,init-method
属性的属性值就对应初始化方法的名称,所以我们的bean应该是如下定义。
<bean name="world" class="com.app.World"/>
<!-- 通过init-method属性指定初始化方法名称 -->
<bean id="hello" class="com.app.Hello" init-method="init">
<property name="world" ref="world"/>
</bean>
init-method
和destroy-method
的用法和配置等基本上都是一样的,所以对于使用destroy-method
来指定ApplicationContext
销毁前的回调方法的用法就不再赘述了。
如果我们的初始化方法或销毁方法的名称大都是一样的,在通过init-method
和destroy-method
进行指定的时候我们就没有必要一个个bean
都去指定了,Spring允许我们在最顶级的beans元素上指定默认的初始化后回调方法和销毁前的回调方法名称,这样对于没有指定init-method
或destroy-method
的bean将默认将其中default-init-method
或default-destroy-method
属性值对应名称的方法(如果存在的话)视为初始化后的回调方法或销毁前的回调方法。这是通过default-init-method
和default-destroy-method
属性来定义的。
<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"
default-init-method="init" default-destroy-method="destroy">
</beans>
以上表示定义默认的初始化后回调方法名称为init,默认的销毁前回调方法名称为destroy。
当定义了default-init-method
或default-destroy-method
以后,如果我们的某个bean对应的初始化后回调方法名称或销毁前的回调方法名称与默认定义的不一样,则我们可以在对应的bean上通过init-method
或destroy-method
指定该bean自身的回调方法名称,即bean上定义的回调方法名称将会比默认定义拥有更高的优先级。
9.3 使用JSR-250标准的注解
关于bean的生命周期回调方法,Spring也会JSR-250
标准注解做了支持,即在bean完全初始化后将回调使用@PostConstruct
标注的方法,在销毁ApplicationContext
前将回调使用@PreDestroy
标注的方法。
针对之前的示例,如果我们现在把定义的bean定义成如下这样,即没有在bean上通过init-method
和destroy-method
指定初始化方法和销毁方法。
<bean name="world" class="com.app.World"/>
<bean id="hello" class="com.app.Hello">
<property name="world" ref="world"/>
</bean>
当然,这里也不考虑全局性的init-method
和destroy-method
方法,如果我们希望在id为“hello”的bean被初始化后回调其中的init()
方法,在销毁前回调其中的destroy()
方法,我们就可以通过@PostConstruct
和@PreDestroy
进行如下定义。
public class Hello {
private World world;
/**
* 该方法将被用来作为初始化方法,在当前bean被完全初始化后被调用
*/
@PostConstruct
public void init() {
Assert.notNull(world, "world should not be null.");
}
@PreDestroy
public void destroy() {
System.out.println("---------destroy-----------");
}
public void setWorld(World world) {
this.world = world;
}
}
使用JSR-250
标准指定初始化后的回调方法以及销毁前的回调方法时,如果我们希望将多个方法都作为对应的回调方法进行回调,则可以在多个方法上同时使用对应的注解进行标注,Spring
将依次执行对应的方法。
public class Hello {
private World world;
@PostConstruct
public void init() {
System.out.println("-----------init-------------");
}
/**
* 该方法将被用来作为初始化方法,在当前bean被完全初始化后被调用
*/
@PostConstruct
public void init2() {
Assert.notNull(world, "world should not be null.");
}
@PreDestroy
public void destroy() {
System.out.println("------------destroy----------------");
}
@PreDestroy
public void destroy2() {
System.out.println("---------destroy2-----------");
}
public void setWorld(World world) {
this.world = world;
}
}
9.4 混合使用三种方式
Spring
允许我们混合使用上述介绍的三种方式来指定对应的回调方法。当对于同一个bean使用三种方式指定了同一个方法作为初始化后的回调方法或销毁前的回调方法,则对应的回调方法只会被执行一次。然而,当对于同一个bean使用两种或三种方式指定的回调方法不是同一个方法时,Spring
将依次执行使用不同的方式指定的回调方法。对于初始化后的回调方法而言,具体规则如下:
- 使用@PostConstruct标注的方法。
- 实现InitializingBean接口后的回调方法afterPropertiesSet()方法。
- 通过init-method或default-init-method指定的方法。
对于销毁前的回调方法而言,其规则是一样的:
- 使用@PreDestroy标注的方法。
- 实现DisposableBean接口后的回调方法destroy()方法。
- 通过destroy-method或default-destroy-method指定的方法。
(注:本文是基于Spring4.1.0所写)
相关推荐
本篇文章主要介绍了详解Spring中bean生命周期回调方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Spring Bean 的生命周期 > Spring Bean 的生命周期简单易懂。在一个 bean 实例被初始化时,需要执行一系列的初 始化操作以达到可用的状态。同样的,当一个 bean 不在被调用时需要进行相关的析构操 作,并从 bean ...
主要介绍了Spring生命周期回调与容器扩展详解,具有一定借鉴价值,需要的朋友可以参考下。
Spring介绍 1. Spring 2. 使用spring的主要目的 3. Spring的模块 Ejb容器(以前是) Ioc容器(现在的控制权) 控制反转Ioc(Invertion of ...12. 定义IoC容器管理的javabean的生命周期回调方法 13. 接口FactoryBean的使用
8.3.1 使用模板和回调机制 8.3.2 Spring为不同持久化技术所提供的模板类 8.4 数据源 8.4.1 配置一个数据源 8.4.2 获取JNDI数据源 8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础...
4.6.1 生命周期回调. 69 4.6.1.1 初始化回调 70 4.6.1.2 销毁回调.. 70 4.6.1.3 默认的初始化和销毁方法 71 4.6.1.4 组合生命周期机制.. 72 4.6.1.5 启动和关闭回调 73 4.6.1.6 在非...
8.3.1 使用模板和回调机制 8.3.2 Spring为不同持久化技术所提供的模板类 8.4 数据源 8.4.1 配置一个数据源 8.4.2 获取JNDI数据源 8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础...
7.3.1. 通知的生命周期 7.3.2. Spring里的通知类型 7.3.2.1. 拦截around通知 7.3.2.2. 前置通知 7.3.2.3. 异常通知 7.3.2.4. 后置通知 7.3.2.5. 引入通知 7.4. Spring里的advisor(Advisor) API 7.5. 使用...
3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...
12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...
3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...
12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...
Spring数据箱 项目的主要目标是使使用新数据访问技术...支持生命周期回调事件(保存之前/之后等) 基于Java的配置 注意:复合主键必须包含Crate支持的。 快速开始 检出项目存储库,并从外壳程序/终端发出以下命令
spring3.1中文参考文档,南磊翻译,现在有4章,目录如下: 第一部分 Spring framework概述.......................................................................................................................
生命周期比较短的creator可以得到更好的安全性,通过不同的应用情况设置适合的生命周期. 低内存开销 在访问量比较大的情况下,可以不用担心发生内存泄露的情况. 配置一个creator的创建和远程方法调用设置: ...
10.8.1 实体的生命周期与回调事件 444 10.8.2 使用专门的监听器实现回调 448 10.8.3 为全部实体配置默认监听器 450 10.8.4 排除监听器 452 10.9 本章小结 455 第11章 JPA的查询支持 456 11.1 查询API 457 11.1.1 ...
{7.2}回调模式与FileFilter}{104}{section.7.2} {7.3}\ttfamily RandomAccessFile}{106}{section.7.3} {7.4}基本类型数据序列化}{108}{section.7.4} {7.5}String的序列化}{109}{section.7.5} {7.6}InputStream...