最近工作需要得到sping中的每个事物需要执行的sql,称机会简单研究了一下spring的事务,项目中管理事务比较简单,用TransactionTemplate,就直接以TransactionTemplate为入口开始学习。
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);
}
}
}

总结:
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");
}
}

spring InitializingBean接口的更多相关文章

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

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

  2. spring中InitializingBean接口使用理解

    InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法. 测试程序如下: imp ...

  3. Spring中的InitializingBean接口的使用

    InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法. 测试,如下: imp ...

  4. spring中InitializingBean接口使用理解(转)

    InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法. 测试程序如下: imp ...

  5. spring 中 InitializingBean 接口使用理解

    前言:这两天在看 spring 与 quart 的集成,所以了解到 spring 是如何初始化 org.springframework.scheduling.quartz.SchedulerFacto ...

  6. spring常用接口 InitializingBean的作用

    工作中遇到spring接口中的InitializingBean接口.浅浅的解说一下. --------------------------------------------------------- ...

  7. 【spring】InitializingBean接口

    apollo 源码中有这么一个类 public class ReleaseMessageScanner implements InitializingBean @Override public voi ...

  8. Spring中的InitializingBean接口

    InitializingBean接口为bean提供了初始化方法的方式,它只有afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法. 测试程序如下: impo ...

  9. Spring核心接口之InitializingBean

    一.InitializingBean接口说明 InitializingBean接口为bean提供了属性初始化后的处理方法,它只包括afterPropertiesSet方法,凡是继承该接口的类,在bea ...

随机推荐

  1. Java面试知识的认知描述

    连接池:同时操作连接数据库,创建一个连接池,池子里创建一万个数据库链接.根据系统运行情况关闭链接.高峰期链接达到最大MAX进行排队,对在用的链接实现失效时间.有几种:tomcat请求服务器(serve ...

  2. Mysql修改root用户密码 For Mac 报错:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

    环境 Mysql版本:5.7.12 操作系统:OSX 10.11 安装文件:.dmg文件 MySQL:mysql-5.7.12-osx10.11-x86_64.dmg(注意5.7跟之前的字段有些不同, ...

  3. 图像卷积、相关以及在MATLAB中的操作

    图像卷积.相关以及在MATLAB中的操作 2016年7月11日 20:34:35, By ChrisZZ 区分卷积和相关 图像处理中常常需要用一个滤波器做空间滤波操作.空间滤波操作有时候也被叫做卷积滤 ...

  4. 【uoj149】 NOIP2015—子串

    http://uoj.ac/problem/149 (题目链接) 题意 给出两个字符串A.B,问从A中取出k个互不重叠的子串按顺序组成B的方案数. Solution 一看这种题目就是字符串dp,字符串 ...

  5. BZOJ1010 [HNOI2008]玩具装箱toy

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  6. dedecms /member/uploads_edit.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms 5.3版本下的member/uploads_edit.p ...

  7. ubuntu14.04 配置中文输入法

    ubuntu14.04自带中文输入法,只要配置就可以了. 1.安装中文支持 System Settings -->  Language Support 点击 install/remove lan ...

  8. Apache 优雅重启 Xampp开机自启 - 【环境变量】用DOS命令在任意目录下启动服务

    D:\xampp\apache\bin\httpd.exe" -k runservice Apache 优雅重启 :httpd -k graceful Xampp开机自启动  参考文献:ht ...

  9. 生活中的MVC模式,一个吃货的理解。

    以下是生活中对于MVC模式的领悟,虽然可笑,轻喷. 2015年 8月 26日 M  => Model       模型 我认为叫做模具更好的理解.批量加工生产具有相同特征的东西.        ...

  10. css003 选择器:明确设置哪些样式

    css003 选择器:明确设置哪些样式 1.每个样式的两个部分:选择器和声明块 1.标签选择器:整体控制 2.类选择器:精确控制(.+字母.数字.连字符或下划线) Css允许的类名为.+字母.数字.连 ...