`
234390216
  • 浏览: 10195761 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:460930
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1772003
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1395627
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:393961
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:678309
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:529373
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1178882
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:462312
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:150225
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:66926
社区版块
存档分类
最新评论

Spring(09)——bean生命周期回调方法

阅读更多

9 生命周期回调方法

对于Spring bean来讲,我们默认可以指定两个生命周期回调方法。一个是在ApplicationContextbean初始化,包括注入对应的依赖后的回调方法;另一个是在ApplicationContext准备销毁之前的回调方法。要实现这种回调主要有三种方式:实现特定的接口、在XML配置文件中指定回调方法和使用JSR-250标准的注解。

9.1 实现特定接口

针对bean初始化后的回调和ApplicationContext销毁前的回调,Spring分别为我们了提供了InitializingBeanDisposableBean接口供用户实现,这样Spring在需要进行回调时就会调用对应接口提供的回调方法。

9.1.1 InitializingBean

InitializingBean是用来定义ApplicationContext在完全初始化一个bean以后需要需要回调的方法的,其中只定义了一个afterPropertiesSet()方法。如其名称所描述的那样,该方法将在ApplicationContext将一个bean完全初始化,包括将对应的依赖项都注入以后才会被调用。InitializingBean的完全定义如下。

public interface InitializingBean {

	void afterPropertiesSet() throws Exception;

}

由于InitializingBeanafterPropertiesSet()方法会在依赖项都进行注入以后再回调,所以该方法通常会用来检查必要的依赖注入,以使我们能够在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-methoddestroy-method的用法和配置等基本上都是一样的,所以对于使用destroy-method来指定ApplicationContext销毁前的回调方法的用法就不再赘述了。

如果我们的初始化方法或销毁方法的名称大都是一样的,在通过init-methoddestroy-method进行指定的时候我们就没有必要一个个bean都去指定了,Spring允许我们在最顶级的beans元素上指定默认的初始化后回调方法和销毁前的回调方法名称,这样对于没有指定init-methoddestroy-method的bean将默认将其中default-init-methoddefault-destroy-method属性值对应名称的方法(如果存在的话)视为初始化后的回调方法或销毁前的回调方法。这是通过default-init-methoddefault-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-methoddefault-destroy-method以后,如果我们的某个bean对应的初始化后回调方法名称或销毁前的回调方法名称与默认定义的不一样,则我们可以在对应的bean上通过init-methoddestroy-method指定该bean自身的回调方法名称,即bean上定义的回调方法名称将会比默认定义拥有更高的优先级。

9.3 使用JSR-250标准的注解

关于bean的生命周期回调方法,Spring也会JSR-250标准注解做了支持,即在bean完全初始化后将回调使用@PostConstruct标注的方法,在销毁ApplicationContext前将回调使用@PreDestroy标注的方法。
针对之前的示例,如果我们现在把定义的bean定义成如下这样,即没有在bean上通过init-methoddestroy-method指定初始化方法和销毁方法。

	<bean name="world" class="com.app.World"/>
	<bean id="hello" class="com.app.Hello">
		<property name="world" ref="world"/>
	</bean>

当然,这里也不考虑全局性的init-methoddestroy-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所写)

 

1
0
分享到:
评论
3 楼 snfdf 2017-09-14  
234390216 写道
snfdf 写道
@PostConstruct和@PreDestroy没有执行,百度了半天也没找到答案,请问博主这是怎么回事啊?谢谢。
public class World {

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

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

<bean name="world" class="com.app.World"/>
然后maven只引了这两个包
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

iteye现在有留言上面那个消息数字那都不给提示了。
你的这种情况应该是你没启用对注解的支持。加上<context:annotation-config/>试试。

是的,我后来发现没有配开启注解支持,现在已经好了,多谢。
2 楼 234390216 2017-09-14  
snfdf 写道
@PostConstruct和@PreDestroy没有执行,百度了半天也没找到答案,请问博主这是怎么回事啊?谢谢。
public class World {

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

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

<bean name="world" class="com.app.World"/>
然后maven只引了这两个包
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

iteye现在有留言上面那个消息数字那都不给提示了。
你的这种情况应该是你没启用对注解的支持。加上<context:annotation-config/>试试。
1 楼 snfdf 2017-09-11  
@PostConstruct和@PreDestroy没有执行,百度了半天也没找到答案,请问博主这是怎么回事啊?谢谢。
public class World {

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

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

<bean name="world" class="com.app.World"/>
然后maven只引了这两个包
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

相关推荐

    详解Spring中bean生命周期回调方法

    本篇文章主要介绍了详解Spring中bean生命周期回调方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    开源框架面试专题及答案.pdf

    Spring Bean 的生命周期 &gt; Spring Bean 的生命周期简单易懂。在一个 bean 实例被初始化时,需要执行一系列的初 始化操作以达到可用的状态。同样的,当一个 bean 不在被调用时需要进行相关的析构操 作,并从 bean ...

    Spring生命周期回调与容器扩展详解

    主要介绍了Spring生命周期回调与容器扩展详解,具有一定借鉴价值,需要的朋友可以参考下。

    spring的详细介绍

    Spring介绍 1. Spring 2. 使用spring的主要目的 3. Spring的模块 Ejb容器(以前是) Ioc容器(现在的控制权) 控制反转Ioc(Invertion of ...12. 定义IoC容器管理的javabean的生命周期回调方法 13. 接口FactoryBean的使用

    Spring.3.x企业应用开发实战(完整版).part2

    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 数据库事务基础...

    Spring 3 Reference中文

    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 在非...

    Spring3.x企业应用开发实战(完整版) part1

    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 数据库事务基础...

    Spring-Reference_zh_CN(Spring中文参考手册)

    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. 使用...

    Spring中文帮助文档

    3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...

    Spring 2.0 开发参考手册

    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 API

    3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...

    spring chm文档

    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-data-crate

    Spring数据箱 项目的主要目标是使使用新数据访问技术...支持生命周期回调事件(保存之前/之后等) 基于Java的配置 注意:复合主键必须包含Crate支持的。 快速开始 检出项目存储库,并从外壳程序/终端发出以下命令

    spring3.1中文参考文档

    spring3.1中文参考文档,南磊翻译,现在有4章,目录如下: 第一部分 Spring framework概述.......................................................................................................................

    DWR.xml配置文件说明书(含源码)

    生命周期比较短的creator可以得到更好的安全性,通过不同的应用情况设置适合的生命周期.  低内存开销 在访问量比较大的情况下,可以不用担心发生内存泄露的情况. 配置一个creator的创建和远程方法调用设置: ...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    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 ...

    Java学习笔记-个人整理的

    {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...

Global site tag (gtag.js) - Google Analytics