【spring的InitializingBean的 afterPropertiesSet 方法 和 init-method配置的 区别联系】

InitializingBean

Spring的InitializingBean为bean提供了定义初始化方法的方式。InitializingBean是一个接口,它仅仅包含一个方法:afterPropertiesSet()。

Bean实现这个接口,在afterPropertiesSet()中编写初始化代码:

package research.spring.beanfactory.ch4; import org.springframework.beans.factory.InitializingBean; class LifeCycleBean implements InitializingBean{

void afterPropertiesSet() throws Exception { System. out .println("LifeCycleBean initializing..."); } }

在xml配置文件中并不需要对bean进行特殊的配置:

xml version="1.0" encoding="UTF-8" ?> DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >

< beans >

< bean name ="lifeBean" class ="research.spring.beanfactory.ch4.LifeCycleBean">

>

< /beans >

编写测试程序进行测试:

package research.spring.beanfactory.ch4; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; public class LifeCycleTest { static void main(String[] args) { XmlBeanFactory factory= newXmlBeanFactory( new ClassPathResource("research/spring/beanfactory/ch4/context.xml")); factory.getBean("lifeBean"); } }

运行上面的程序我们会看到:“LifeCycleBean initializing...”,这说明bean的afterPropertiesSet已经被Spring调用了。

Spring在设置完一个bean所有的合作者后,会检查bean是否实现了InitializingBean接口,如果实现就调用bean的afterPropertiesSet方法。

SHAPE  /* MERGEFORMAT

装配 bean的合作者

查看 bean是否实现 InitializingBean 接口

调用 afterPropertiesSet 方法

Spring虽然可以通过InitializingBean完成一个bean初始化后对这个bean的回调,但是这种方式要求bean实现 InitializingBean接口。一但bean实现了InitializingBean接口,那么这个bean的代码就和Spring耦合到一起了。通常情况下我不鼓励bean直接实现InitializingBean,可以使用Spring提供的init-method的功能来执行一个bean 子定义的初始化方法。

写一个java class,这个类不实现任何Spring的接口。定义一个没有参数的方法init()。

package research.spring.beanfactory.ch4;

publicclass LifeCycleBean{

publicvoid init(){

System. out .println("LifeCycleBean.init...");

}

}

在Spring中配置这个bean:

xml version="1.0" encoding="UTF-8" ?> DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd" >< beans >< bean name ="lifeBean" class ="research.spring.beanfactory.ch4.LifeCycleBean"

init-method ="init"> bean > beans >

当Spring实例化lifeBean时,你会在控制台上看到” LifeCycleBean.init...”。

Spring要求init-method是一个无参数的方法,如果init-method指定的方法中有参数,那么Spring将会抛出 java.lang.NoSuchMethodException

init-method指定的方法可以是public、protected以及private的,并且方法也可以是final的。

init-method指定的方法可以是声明为抛出异常的,就像这样:

final protected void init() throws Exception{

System.out.println("init method...");

if(true) throw new Exception("init exception");

}

如果在init-method方法中抛出了异常,那么Spring将中止这个Bean的后续处理,并且抛出一个 org.springframework.beans.factory.BeanCreationException异常。

InitializingBean和init-method可以一起使用,Spring会先处理InitializingBean再处理init-method。

org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory完成一个Bean初始化方法的调用工作。 AbstractAutowireCapableBeanFactory是XmlBeanFactory的超类,再 AbstractAutowireCapableBeanFactory的invokeInitMethods方法中实现调用一个Bean初始化方法:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.java:

// ……

//在一个bean的合作者设备完成后,执行一个bean的初始化方法。 protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mergedBeanDefinition)

throws Throwable {

// 判断bean是否实现了InitializingBean接口 if (bean instanceof InitializingBean) {

if (logger.isDebugEnabled()) {

logger.debug("Invoking afterPropertiesSet() on bean with name '"+ beanName +"'");

}

// 调用afterPropertiesSet方法

((InitializingBean) bean).afterPropertiesSet();

}

// 判断bean是否定义了init-method if (mergedBeanDefinition!= null &&mergedBeanDefinition.getInitMethodName() != null ) {

//调用invokeCustomInitMethod方法来执行init-method定义的方法

invokeCustomInitMethod(beanName, bean, mergedBeanDefinition.getInitMethodName());

} }

// 执行一个bean定义的init-method方法 protected void invokeCustomInitMethod(String beanName, Object bean, String initMethodName)

throws Throwable {

if (logger.isDebugEnabled()) {

logger.debug("Invoking custom init method '"+ initMethodName +"' on bean with name '"+ beanName +"'");

}

// 使用方法名,反射Method对象

Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);

if (initMethod ==null) {

thrownew NoSuchMethodException(

"Couldn't find an init method named '"+ initMethodName +"' on bean with name '"+ beanName +"'");

}

// 判断方法是否是public if (!Modifier.isPublic(initMethod.getModifiers())) {

//设置accessible为true,可以访问private方法。 initMethod.setAccessible( true );

}

try {

//反射执行这个方法

initMethod.invoke(bean, (Object[]) null );

}

catch (InvocationTargetException ex) {

throw ex.getTargetException();

} }

// ………..

通过分析上面的源代码我们可以看到,init-method是通过反射执行的,而afterPropertiesSet是直接执行的。所以 afterPropertiesSet的执行效率比init-method要高,不过init-method消除了bean对Spring依赖。在实际使用时我推荐使用init-method。

需要注意的是Spring总是先处理bean定义的InitializingBean,然后才处理init-method。如果在Spirng处理InitializingBean时出错,那么Spring将直接抛出异常,不会再继续处理init-method。

如果一个bean被定义为非单例的,那么afterPropertiesSet和init-method在bean的每一个实例被创建时都会执行。单例 bean的afterPropertiesSet和init-method只在bean第一次被实例时调用一次。大多数情况下 afterPropertiesSet和init-method都应用在单例的bean上。

InitializingBean和init-method的更多相关文章

  1. SSH项目练习的时候报错:[applicationContext.xml]: Invocation of init method failed;

    这里是控制台的报错信息:org.springframework.beans.factory.BeanCreationException: Error creating bean with name ' ...

  2. The init method

    The init method is a special method that gets invoked when an object is instantiated. Its full name ...

  3. Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; neste

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFacto ...

  4. Invocation of init method failed; nested exception is org.hibernate.HibernateException: could not instantiate RegionFactory [org.hibernate.cache.impl

    严重: Exception sending context initialized event to listener instance of class org.springframework.we ...

  5. java代码中init method和destroy method的三种使用方式

    在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. ...

  6. MyBatis笔记----报错:Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/ij34/mybatis/applicationContext.xml]: Invocation of init method failed; nested exception is org.sp

    四月 05, 2017 4:51:02 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRef ...

  7. org.springframework.beans.factory.BeanCreationException,Invocation of init method failed,Context initialization failed

    G:\javaanzhuang\apache-tomcat-\bin\catalina.bat run [-- ::,] Artifact ssm_qingmu02_web:war exploded: ...

  8. Invocation of init method failed; nested exception is java.text.ParseException: '?' can only be specfied for Day-of-Month or Day-of-Week.

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronTrigger' ...

  9. spring init method destroy method

    在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. ...

  10. aused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method fai

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'roleDaoImpl' ...

随机推荐

  1. 通过 XtraBackup 实现不停机不锁表搭建主从同步

    简介 Xtrabackup是由 Percona 开发的一个开源软件,可实现对 InnoDB 的数据备份,支持在线热备份(备份时不影响数据读写).备份时,Xtrabackup 会将 Master 的 b ...

  2. An unexpected exception occurred while creating a change object. see the error log for more details

    今天再给Android项目工程中的包重命名时出现了这个错误(之前重命名的时候就没有出现,郁闷): An unexpected exception occurred while creating a c ...

  3. C++调试 输出数组内容和数组名

    #include <cstdio> using namespace std; //函数定义 #define printArr(arr,n,format) \ printf("%s ...

  4. 编辑时snapping的添加

    原文 编辑时snapping的添加 注意需要在编辑模式下进行snapping的添加(也即先需要使用IEngineEditor进入编辑状态): IMapControl3 mMap = (IMapCont ...

  5. java读取目录下所有csv文件数据,存入三维数组并返回

    package dwzx.com.get; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; ...

  6. STL中用erase()方法遍历删除元素 .xml

    pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...

  7. 1005acm罚时

    ACM国际大学生程序设计竞赛是由国际计算机学会主办的,一项旨在展示大学生创新能力.团队精神和在压力下编写程序.分析和解决问题能力的年度竞赛.参赛队伍最多由三名参赛队员组成,竞赛中一般命题10-13题, ...

  8. 如何引用CSS样式表

      如何使用样式 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化.有以下三种方式来插入样式表: 1.外部样式表 当样式需要被应用到很多页面的时候,外部样式表将是理想的选择.使用外部样式 ...

  9. 使用 XMPP 构建一个基于 web 的通知工具——转

    Inserting of file(使用 XMPP 构建一个基于 web 的通知工具.docx) failed. Please try again. http://www.ibm.com/develo ...

  10. Time vs Story Points Estimation [转]

    One of the most common questions we get is whether to estimate in time or points. It seems like poin ...