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中使用 ...
随机推荐
- Context.startActivity出现AndroidRuntimeException
转:http://hi.baidu.com/huaxinchang/item/e1a771cf4d424312b77a2416 昨天做了一个Activity的启动动画,效果是点击桌面图标先出现动画后启 ...
- 【Ubuntu】ubuntu系统下python3和python2环境自由切换
shell里执行: sudo update-alternatives --install /usr/bin/python python /usr/local/lib/python2.7 100sudo ...
- maven 添加jetty 支持
maven jetty run 即可 配置 <plugin> <groupId>org.mortbay.jetty</groupId> <artifactI ...
- tf.constant
tf.constant constant( value, dtype=None, shape=None, name='Const', verify_shape=False ) 功能说明: 根据 val ...
- phpmyadmin 各种技巧拿 webshell
site.com/phpMyAdminsite.com/sql D:\wamp\www 账号还有密码 root 密码第一种CREATE TABLE `mysql`.`darkmoon` (`darkm ...
- Android动画知识汇总
Interpolator(插值器) Interpolatort通常在动画中使用,主要来改变动画变化率.常用的有下面几种Interpolator,下面图文解说下: AccelerateDecelerat ...
- MyBatis 之 SqlSessionManager 源码分析
MyBatis 的 4 个基本构成: SqlSessionFactoryBuilder(构造器): 根据配置信息或者代码来生成 SqlSessionFactory(工厂接口) SqlSessionFa ...
- AndroidA——背景选择器selector用法汇总(一)
一.创建xml文件,位置:drawable/xxx.xml,同目录下记得要放相关图片 <?xml version="1.0" encoding="utf-8&quo ...
- redis+nginx+tomcat故障大全
tomcat+nginx+redis中 redis死掉了???确实是防火墙问题centos7用的firewalldfirewalld默认已经安装并启用了,如果需要nginx可以访问需要执行以下命令:# ...
- jQuery(十一):jQuery的事件
一.jQuery事件的分类 jQuery事件是对JavaScript事件的封装,常用事件分类如下: 1.基础事件 window事件. 鼠标事件. 键盘事件. 表单事件. 2.复合事件是多个事件的组合 ...