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中使用 ...
随机推荐
- 【教程】ubuntu下安装samba服务器
一.准备工作 首先更新 software sources, 找到最快的源 lcw@ubuntu:~$ sudo apt-get update 二.安装samba lcw@ubuntu:~$ sudo ...
- 解决问题:swiper动态加载图片后无法滑动
原因:swiper在初始化的时候会扫描swiper-wrapper下面的swiper-slide的个数,从而完成初始化,但是由于动态加载时在初始化之后的动作,所以导致无法滑动. 解决方案 1:在动态获 ...
- Emacs文件命令
[文件]----------------------------------------C-x C-f 读取文件到Emacs C-x r 只读的方式打开一个文件C-x C-q 清除一个窗口的只读属性 ...
- python 下载虾米音乐
#!/usr/bin/env python2 # coding:utf-8 import urllib import re import sys import urllib2 # xml => ...
- python Anaconda 安装管理包,开发环境
在自己的电脑上安装Anaconda,用conda create创建一个python 2.7版本的environment.今后我们的程序都在这个环境下执行 0.download anaconda and ...
- WebSphere ILog JRules 域的介绍和定制
WebSphere ILog JRules 域的介绍和定制 引言 随着企业业务的不断发展,越来越多的企业正经历着以下的情形: 企业需要对于业务系统的频繁变化做出及时的关注和响应,例如,竞争对手或经济环 ...
- mysql的导入导出工具mysqldump命令详解
导出要用到MySQL的mysqldump工具,基本用法是: shell> mysqldump [OPTIONS] database [tables] 如果你不给定任何表,整个数据库将被导出. 通 ...
- (转) MyBatis(1)——快速入门
MyBatis 简介 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为 ...
- B2C和B2B之间有多大差距
从产品应用的角度,我们团队经历了企图将B2C系统套用到B2B业务流程上的阶段,对于自营业务这还勉强可以实施,但对于外部用户的实施难度就太大了,用户体验也不好.这个过程中,我只关注了技术范畴的迭代速度. ...
- Android——listview android:cacheColorHint,android:listSelector属性作用
ListView是常用的显示控件,默认背景是和系统窗口一样的透明色,如果给ListView加上背景图片,或者背景颜色时,滚动时listView会黑掉, 原因是,滚动时,列表里面的view重绘时,用的依 ...