先说总结:
1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用
2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖
3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。
4:TransactionTemplate实现InitializingBean接口,主要是判断transactionManager是否已经初始化,如果没有则抛出异常。源码如下:
     public void afterPropertiesSet() {
        if (this.transactionManager == null) {
            throw new IllegalArgumentException("Property 'transactionManager' is required");
        }
    }


TransactionTemplate的源码如下:
public class TransactionTemplate extends DefaultTransactionDefinition
        implements TransactionOperations, InitializingBean{
        .
        .
        .
        }
TransactionTemplate继承了DefaultTransactionDefinition,实现了TransactionOperations,InitializingBean接口。先研究InitializingBean接口
InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法。
测试程序如下:


import org.springframework.beans.factory.InitializingBean;
public class TestInitializingBean implements InitializingBean{

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("ceshi InitializingBean");        
    }
    public void testInit(){
        System.out.println("ceshi init-method");        
    }
}
配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="testInitializingBean" class="com.TestInitializingBean" ></bean>
</beans>
Main主程序如下:
public class Main {
    public static void main(String[] args){
        ApplicationContext context = new FileSystemXmlApplicationContext("/src/main/java/com/beans.xml");
    }
}
运行Main程序,打印如下结果:
ceshi InitializingBean  
这说明在spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法。
问题:实现InitializingBean接口与在配置文件中指定init-method有什么不同?
修改配置文件,加上init-method配置,修改如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="testInitializingBean" class="com.TestInitializingBean" init-method="testInit"></bean>
</beans>
在配置文件中加入init-method="testInit"。
运行Main程序,打印如下结果:
ceshi InitializingBean
ceshi init-method
由 结果可看出,在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init- method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。

这方式在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);
            }
        }
    }


spring InitializingBean的更多相关文章

  1. Spring InitializingBean and DisposableBean example

    In Spring, InitializingBean and DisposableBean are two marker interfaces, a useful way for Spring to ...

  2. Spring InitializingBean 接口以及Aware接口实现的原理

    关于Spring InitializingBean 接口以及Aware接口实现的其实都在 第11步中: finishBeanFactoryInitialization() 方法中完成了3部分的内容: ...

  3. spring InitializingBean接口

    最近工作需要得到sping中的每个事物需要执行的sql,称机会简单研究了一下spring的事务,项目中管理事务比较简单,用TransactionTemplate,就直接以TransactionTemp ...

  4. Spring InitializingBean和init-method

    原文转自:http://blog.csdn.net/shaozheng1006/article/details/6916940 InitializingBean     Spirng的Initiali ...

  5. Spring InitializingBean和ApplicationListener<ContextRefreshedEvent>

    事件机制作为一种编程机制,在许多语言中都提供了支持.JAVA语言也不例外,java中的事件机制的参与者有3种角色: 1.event object 2.event source 3.event list ...

  6. Spring InitializingBean init-method @PostConstruct 执行顺序

    Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下三种:   通过实现 Initializing ...

  7. spring InitializingBean和DisposableBean init-method 和destroy-method @PostConstruct @PreDestroy

    对于初始化函数: @PostConstruct 注解的方法 InitializingBean接口定义的回调afterPropertiesSet() Bean配置中自定义的初始化函数 对于析构则与上相同 ...

  8. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->关于spring framework中的beans

    Spring framework中的beans 1.概述 bean其实就是各个类实例化后的对象,即objects spring framework的IOC容器所管理的基本单元就是bean spring ...

  9. 译:Spring框架参考文档之IoC容器(未完成)

    6. IoC容器 6.1 Spring IoC容器和bean介绍 这一章节介绍了Spring框架的控制反转(IoC)实现的原理.IoC也被称作依赖注入(DI).It is a process wher ...

随机推荐

  1. hadoop执行wordcount例子

    1:下载hadoop.http://mirror.esocc.com/apache/hadoop/common/hadoop-1.2.1/hadoop-1.2.1.tar.gz 2:解压. tar - ...

  2. 【Oracle 】pctfree和pctused详解

    一.建立表时候,注意PCTFREE参数的作用 PCTFREE:为一个块保留的空间百分比,表示数据块在什么情况下可以被insert,默认是10,表示当数据块的可用空间低于10%后,就不可以被insert ...

  3. QQMacMgr for Mac(腾讯电脑管家)安装

    1.软件简介    腾讯电脑管家是 macOS 系统上一款由腾讯公司带来到的安全管理软件.功能有垃圾清理.软件仓库.小火箭加速和防钓鱼等.而在视觉 UI 上,导入星空概念,操作过场动画全部以星空为题材 ...

  4. redis常用性能分析命令

    一.连接 src/redis-cli -h 10.20.137.141 -p 6379 >auth 123456789 src/redis-cli -h 10.20.137.141 -p 637 ...

  5. Kibana常用命令

    一.范围(>500) totalTime: [500 TO *] 二.不等于 NOT monitorName: "XXX" 三.字符匹配 正则表达式:    +url:/.* ...

  6. mysql 5.5数据库主从配置步骤详解

    上次给大家介绍了mysql 5.1主从搭建配置教程,这次我们来实现mysql 5.5的主从复制,其实大体上配置是差不多的,只有点细微的差别. 系统:centos 5.x 需要的软件包:mysql-5. ...

  7. CentOS7.2安装pure-ftpd 及其配置项

    CentOS7.2安装FTP(pure-ftpd-1.0.43) 原文链接: https://www.linuxidc.com/Linux/2016-10/135971.htm [日期:2016-10 ...

  8. 稀疏傅里叶变换(sparse FFT)

    作者:桂. 时间:2018-01-06  14:00:25 链接:http://www.cnblogs.com/xingshansi/p/8214122.html 前言 对于数字接收来讲,射频域随着带 ...

  9. java.lang.RuntimeException: Date pattern must be set for column update_time in the schema of component

    使用Talend open studio  ,从mysql数据源中读取数据,将数据导出到excel文档,另外一个mysql数据库,和一个普通文件,遇到标题的错误,模型如下图所示: tMap将30.7中 ...

  10. 【转】在 Windows 10 下,配置 Kinect v2 可用于 Windows Hello 验证身份

    先要修改下注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DriverFlighting\Partner如果没有这个文件夹就创建一个吧 然后创建一个字符串类型的变量T ...