【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. 【Python】入门 list有些不懂

    # -*- coding: utf-8 -*- # -*- coding: cp936 -*- 首行加这个 代码里就可以加注释 raw_input("Press Enter Exit&quo ...

  2. mac os 系统密码正确的 但是进不了系统

    今天开始重新学习C 但是一早起来开机进不了系统 密码明明正确的 无语了,后来打苹果售后电话解决了. 今天记录下如何解决的,以后万一又出现这种问题,至于原因嘛 我也不知道 有可能跟我装的双系统有关系.只 ...

  3. C#利用最新版的WPS实现导入导出

    微软的EXCEl操作相信大家也知道,不方便,安装包太大,而且表格的数据量也只有6000多(是6000多还是60000多我就忘记了),在导出导入大量数据的就没办法,而wsp表格则实现了百万数据的容量,而 ...

  4. Sde表结构分析

    原文 Sde表结构分析 今天开始想分析一下sde的表结构,希望能够弄明白sde一个要素类的每个Feature是如何存储的. 弄ArcSDE的人都知道,ArcSDE内一个要素类在关系数据库(以MS SQ ...

  5. delphi 中 $是什么意思 串口中使用

    delphi 中 $是什么意思? 比如:$41----$5A 意识是26个字母, 可以用$来表示? $在delphi 中还可以怎么用?1.表示16进制,$41就是65,第一个字母的ASCII值 pro ...

  6. cocos2dx 水波纹Shader

    // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////// ...

  7. multi-catch和try-catch异常处理

    multi-catch属于JDK1.7之后出现的,举例如下: class FactoryTest { public static Fruits getInstance(String className ...

  8. 黑马程序员——Foundation中的OC结构体

    <span style="font-size:14px">------<a target="_blank" href="http:/ ...

  9. Office2016 转换零售版为VOL版

    @echo off :ADMIN openfiles >nul >nul ||( echo Set UAC = CreateObject^("Shell.Application& ...

  10. Java执行groovy脚本

    Binding binding = new Binding(); binding.setVariable("foo", new Integer(2)); GroovyShell s ...