先说总结:
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. iOS – 单例模式写一次就够了

    一. 单例模式简介 单例模式的作用 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问 从而方便地控制了实例个数,并节约系统资源 单例模式的使用场合 在整个应用程序中,共享一份资源( ...

  2. 安装cacti

    操作介绍如下: http://foreveryan.blog.51cto.com/3508502/775558 安装如下: 英文地址:http://www.cyberciti.biz/faq/fedo ...

  3. 【jsp】配置错误页面

    1,使用JSP方式 如果配置是Jsp时,需要把isErrorPage设置为true, 以及设置 <%@ page language="Java" contentType=&q ...

  4. Git 配置(分布式版本控制系统)

    1.Mac Git 配置文件 既然已经在系统上安装了 Git,你会想要做几件事来定制你的 Git 环境.每台计算机上只需要配置一次,程序升级时会保留配置信息.你可以在任何时候再次通过运行命令来修改它们 ...

  5. 【java基础】Java反射机制

    一.预先需要掌握的知识(java虚拟机)  1)java虚拟机的方法区:  java虚拟机有一个运行时数据区,这个数据区又被分为方法区,堆区和栈区,我们这里需要了解的主要是方法区.方法区的主要作用是存 ...

  6. thinkphp __hash__

    thinkphp会自动在模板文件的表单后加一个__hash__来验证提交,保证一定程序上的安全: 但是有时用不着,可以用: C('TOKEN_ON',false); 关闭这项

  7. MongoDB 学习笔记(9)--- Limit与Skip方法

    MongoDB Limit() 方法 如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的 ...

  8. MySQL -- Fast Index Creation

    1.fast index creation简介 MySQL5.5之后,对innodb表创建或删除辅助索引的效率提升了很多,即增加了新的功能fast index creation.因为MySQL5.5之 ...

  9. User-Agent 信息汇总(拿去就能用)

    # encoding=utf- agents = [ "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) ...

  10. WEB服务器搭建–IIS

    功能作用 IIS是一个World Wide Web server.Gopher server和FTP server全部包容在里面. IIS意味着你能发布网页,并且有ASP(Active Server ...