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中使用 ...
随机推荐
- 原生js实现文件上传
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- hadoop的核心思想【转】
[转自]:http://www.superwu.cn/2014/01/10/963/ 1.1.1. hadoop的核心思想 Hadoop包括两大核心,分布式存储系统和分布式计算系统. 1.1.1.1. ...
- Lintcode: Kth Largest Element 解题报告
Kth Largest Element Find K-th largest element in an array. Note You can swap elements in the array E ...
- 【Python】打印object对象
print (object .__dict__) print (dir(object))
- poj2965(位运算压缩+bfs+记忆路径)
题意:有个4*4的开关,里面有着16个小开关 -+-- ---- ---- '+'表示开关是关着的,'-'表示开关是开着的,只有所有的开关全被打开,总开关才会被打开.现在有一种操作,只要改变某个开关, ...
- swift.org - About Swift 官网关于notes
About Swifthtml, body {overflow-x: initial !important;}html { font-size: 14px; } body { margin: 0px; ...
- TP v5中环境变量在项目中的应用
环境变量,顾名思义就是在不同的系统环境,同一个变量的值可以有所不同. 如开发环境.测试环境与正式环境下,数据库配置.静态资源文件Url前缀.缓存.各种key等配置都不相同,对于提交到仓库中的代码,理论 ...
- PHP——大话PHP设计模式——命名空间和类的自动载入
开发工具:phpstorm phpstudy 命名空间:声明当前文件 类的自动载入
- oozie无法识别hadoopHA中的ns1
[hadoop@dwdev-name1 m_goods_sale_detail]$ oozie job -config job.properties -run Error: E1603 : java. ...
- PCL点云特征描述与提取(2)
点特征直方图(PFH)描述子 正如点特征表示法所示,表面法线和曲率估计是某个点周围的几何特征基本表示法.虽然计算非常快速容易,但是无法获得太多信息,因为它们只使用很少的几个参数值来近似表示一个点的k邻 ...