先说总结:
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. git学习笔记(二)—— 创建版本库&&版本管理

    一.创建版本库 创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录: mkdir gitHub_CXWcd gitHub_CXW git init Initialized empty G ...

  2. ROS学习(七)—— 理解ROS Topic

    一.准备工作 1.打开roscore roscore 2.turtlesim 打开一个turtulesim节点 rosrun turtlesim turtlesim_node 3.turtle key ...

  3. NoSQL 非关系数据库

    NoSQL 数据库的学习 Redis的Windows版本安装 待整理 redis 安装 关于分布式的网站介绍 NOSQL 几个网页 认识MongoDB Mongodb实现副本集和Mongodb副本集的 ...

  4. hibernate的findByExample 外键参数查询解决方案

    用了这么长时间的hibernate/spring,如果不是今天用的findByExample方法到现在还不知道findByExample的机制.惭愧 Class User{String usernam ...

  5. 【struts2】名为redirect的ResultType

    1)基本使用 名称为“redirect”的ResultType,在struts-default.xml里的配置如下: <result-type name="redirect" ...

  6. Oracle 12C -- 统一启动/关闭PDBs

    SQL> select name,open_mode from v$pdbs; NAME OPEN_MODE ------------------------------ ---------- ...

  7. com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 > 1024)

    ### Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 > 1024). You ...

  8. FreeSWITCH增加iLBC编码

    1. 安装ilbc库从第三方库里下载指定版本 git clone https://freeswitch.org/stash/scm/sd/libilbc.git ./bootstrap.sh ./co ...

  9. URL中#号的含义

    一.#的涵义 #代表网页中的一个位置.其右面的字符,就是该位置的标识符.比如, http://www.example.com/index.html#print 就代表网页index.html的prin ...

  10. django http404 详解

    [引子] 今天在看django的官方文档的时候看到get_object_or_404这个函数感觉比较奇怪.这个主要来自于它的功能,如果要查询的对象 存在那么就返回对象:如果对象不存在那么就要报404 ...