Spring中初始化bean和销毁bean的时候执行某个方法的详解
关于在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种:
第一种:通过注解@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
- import javax.annotation.PostConstruct;
- import javax.annotation.PreDestroy;
- public class DataInitializer{
- @PostConstruct
- public void initMethod() throws Exception {
- System.out.println("initMethod 被执行");
- }
- @PreDestroy
- public void destroyMethod() throws Exception {
- System.out.println("destroyMethod 被执行");
- }
- }

第二种是:通过 在xml中定义init-method 和 destory-method方法
- public class DataInitializer{
- public void initMethod() throws Exception {
- System.out.println("initMethod 被执行");
- }
- public void destroyMethod() throws Exception {
- System.out.println("destroyMethod 被执行");
- }
- }

- <bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/>

第三种是:通过bean实现InitializingBean和 DisposableBean接口
- import org.springframework.beans.factory.DisposableBean;
- public class DataInitializer implements InitializingBean,DisposableBean{
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("afterPropertiesSet 被执行");
- }
- @Override
- public void destroy() throws Exception {
- System.out.println("destroy 被执行");
- }
- }

其中第一种和第二种是同一种形式,只不过一种xml配置,另外一种采用注解形式罢了,有很大区别的是第三种,
如果同一个bean同时采用两种方式初始化的时候执行某个方法,首先在执行顺序上就会体现出来。
先执行afterPropertiesSet(),
后执行initMethod()
这里我们看下源码
这方式在spring中是怎么实现的?
通过查看spring的加载bean的源码类(AbstractAutowireCapableBeanFactory)可看出其中奥妙
AbstractAutowireCapableBeanFactory类中的invokeInitMethods讲解的非常清楚,源码如下:
- protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
- throws Throwable {
- //判断该bean是否实现了实现了InitializingBean接口,如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法
- boolean isInitializingBean = (bean instanceof InitializingBean);
- if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
- if (logger.isDebugEnabled()) {
- logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
- }
- if (System.getSecurityManager() != null) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- //直接调用afterPropertiesSet
- ((InitializingBean) bean).afterPropertiesSet();
- return null;
- }
- },getAccessControlContext());
- } catch (PrivilegedActionException pae) {
- throw pae.getException();
- }
- }
- else {
- //直接调用afterPropertiesSet
- ((InitializingBean) bean).afterPropertiesSet();
- }
- }
- if (mbd != null) {
- String initMethodName = mbd.getInitMethodName();
- //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method
- if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
- !mbd.isExternallyManagedInitMethod(initMethodName)) {
- //进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现
- invokeCustomInitMethod(beanName, bean, mbd);
- }
- }

总结:
1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过
init-method指定,两种方式可以同时使用
2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是
init-method方式消除了对spring的依赖
3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。
Spring中初始化bean和销毁bean的时候执行某个方法的详解的更多相关文章
- Spring中属性注入的几种方式以及复杂属性的注入详解
在spring框架中,属性的注入我们有多种方式,我们可以通过set方法注入,可以通过构造方法注入,也可以通过p名称空间注入,方式多种多样,对于复杂的数据类型比如对象.数组.List.Map.Prope ...
- js数组中的find(), findIndex(), filter(), forEach(), some(), every(), map(), reduce()方法的详解和应用实例
1. find()与findIndex() find()方法,用于找出第一个符合条件的数组成员.它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该 ...
- spring的初始化bean,销毁bean之前的操作详解
我所知道的在spring初始化bean,销毁bean之前的操作有三种方式: 第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作 第二种是 ...
- Spring中<ref local=""/>与<ref bean=""/>区别
小 Spring中<ref local=""/>与<ref bean=""/>区别 (2011-03-19 19:21:58) 转载▼ ...
- Spring中的创建与销毁
在bean中添加属性init-method="方法名" destroy-method="方法名" init-method 该方法是由spring容 ...
- spring中整合memcached,以及创建memcache的put和get方法
spring中整合memcached,以及创建memcache的put和get方法: 1:在项目中导入memcache相关的jar包 2:memcache在spring.xml的配置: 代码: < ...
- [转]js中几种实用的跨域方法原理详解
转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...
- [PXE] Linux(centos6)中PXE 服务器搭建,PXE安装、启动及PXE理论详解
[PXE] Linux(centos6)中PXE 服务器搭建,PXE安装.启动及PXE理论详解 本篇blog主要讲述了[PXE] linux(centos)PXE无盘服务器搭建,安装,启动及pxe协议 ...
- Spring初始化Bean或销毁Bean前执行操作的方式
如果想在Spring初始化后,或者销毁前做某些操作,常用的设定方式有三种: 第一种:通过 在xml中定义init-method 和 destory-method方法 推荐使用,缺陷是只能在XML中使用 ...
随机推荐
- convert2utf8withbom
很久以前给同事要的转码bash 当时windows和mac总是出现中文注释乱码的情况,让人心塞的难过.又因为是老项目,现有源码太多了,不可能改模板重新创建.只能跑一遍这个玩意儿了…… #!/bin/b ...
- Asp.Net采集网页方法大全(5种)
/// <summary>方法一:比较推荐 /// 用HttpWebRequest取得网页源码 /// 对于带BOM的网页很有效,不管是什么编码都能正确识别 /// </summar ...
- html+css+jQuery+JavaScript实现tab自动切换功能
tab1.html内容 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...
- C#学习笔记(29)——Linq的实现,Lambda求偶数和水仙花数
说明(2017-11-22 18:15:48): 1. Lambda表达式里面用了匿名委托,感觉理解起来还是挺难的.求偶数的例子模拟了Linq查询里的一个where方法. 2. 蒋坤说求水仙花数那个例 ...
- PHP 图片处理类 错误处理方法:
call an undefined function exif_imagetype() 打开扩展php.ini 将 ; 去掉: extension=php_exif.dll 并将extension=p ...
- sublime Text2下安装php code sniffer插件
为了跟团队保持开发规范的一致性,需要安装sublime Text2的php code sniffer插件,之前是用的phpfmt插件,发现两个规范还是有点不一样,需要再安装php code sniff ...
- Python MQTT订阅获取发布信息字典过滤
起因是因为 订阅的时候,获取到的 MQTT 信息时,第一条信息好像是连接信息,所以需要过滤他. 接收到的数据如下 必须要过滤这个 name : 1 的字典,操作如下: def on_message(c ...
- [转]关于Json格式
从结构上看,所有的数据(data)最终都可以分解成三种类型: 第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),比如"北京"这个单独 ...
- valgrind--CPP程序内存泄露检查工具
内存泄漏是c++程序常见的问题了,特别是服务类程序,当系统模块过多或者逻辑复杂后,很难通过代码看出内存泄漏. valgrind是一个开源的,检测c++程序内存泄漏有效工具,编译时加上-g选项可以定位到 ...
- 问题解决:bash: fork: retry: Resource temporarily unavailable
linux报错: bash: fork: retry: Resource temporarily unavailable 不管是执行什么 登陆不了服务器The server refused to st ...