init-method  是bean (第一次)实例化的时候被调用的。

先看个异常:

INFO: Overriding bean definition for bean 'office' with a different definition: replacing [Generic bean: class [com.baobaotao.Office]; scope=singleton; abstract=false; lazyInit=false; autowireMode=; dependencyCheck=; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [D:\code\ws\spring\hz\spring-learn\target\classes\com\baobaotao\Office.class]] with [Generic bean: class [com.baobaotao.Office]; scope=; abstract=false; lazyInit=false; autowireMode=; dependencyCheck=; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [beans.xml]]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'boss' defined in class path resource [beans.xml]: Invocation of init method failed; nested exception is org.springframework.beans.factory.support.BeanDefinitionValidationException: Couldn't find an init method named 'initBoss' on bean with name 'boss'
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory$.getObject(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:)
at AnnoIoCTest.main(AnnoIoCTest.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
at java.lang.reflect.Method.invoke(Method.java:)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:)
Caused by: org.springframework.beans.factory.support.BeanDefinitionValidationException: Couldn't find an init method named 'initBoss' on bean with name 'boss'
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:)
... more

从 AbstractApplicationContext.getBean 调用,可见,它是在 getBean 阶段被调用的。

再看位于AbstractAutowireCapableBeanFactory的源码:

    protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
String initMethodName = mbd.getInitMethodName();       //默认 nonPublicAccessAllowed 是true , spring 仅仅是根据 配置的名字去 对应的class 中寻找同名方法, 至于是不是 static,public,有没有返回值 都不要紧
final Method initMethod = mbd.isNonPublicAccessAllowed()?BeanUtils.findMethod(bean.getClass(), initMethodName, new Class[]):ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName, new Class[]);
if(initMethod == null) { // 如果那个方法不符合 约定(比如,如果方法有一个参数等等), 那么这里就会返回 null
if(mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Couldn\'t find an init method named \'" + initMethodName + "\' on bean with name \'" + beanName + "\'");
} else {
if(this.logger.isDebugEnabled()) {
this.logger.debug("No default init method named \'" + initMethodName + "\' found on bean with name \'" + beanName + "\'");
} }
} else {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Invoking init method \'" + initMethodName + "\' on bean with name \'" + beanName + "\'");
} if(System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
ReflectionUtils.makeAccessible(initMethod);
return null;
}
}); try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
initMethod.invoke(bean, new Object[]);
return null;
}
}, this.getAccessControlContext());
} catch (PrivilegedActionException var9) {
InvocationTargetException ex = (InvocationTargetException)var9.getException();
throw ex.getTargetException();
}
} else {
try {
ReflectionUtils.makeAccessible(initMethod); // 方法是不是 public 不要紧, 这里会通过反射修改其可见性
initMethod.invoke(bean, new Object[]); // new Object[0] 表明了 那个方法不能有任何参数, 否则就会出现异常。
} catch (InvocationTargetException var8) {
throw var8.getTargetException();
}
} }
}

 init-method & InitializingBean

InitializingBean的原理并不复杂。 首先它是一个接口,它提供了 方法: public void afterPropertiesSet() throws Exception 。 如果我们的类实现了 它,只要我们的类归spring 管理, 那么spring 会在第一次实例化 这个类的bean的时候, 进行这些相关接口的 方法的初始化。  从afterPropertiesSet名字也可知, 这个方法是在 bean完成了所有 属性的设置后 才进行调用的。 也就是说, 方法的初始化会 晚于 属性的初始化。

init-method 和 InitializingBean  是类似的,但其原理还是有所不同的,参见AbstractAutowireCapableBeanFactory 的源码可知:

    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = bean instanceof InitializingBean;
if(isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Invoking afterPropertiesSet() on bean with name \'" + beanName + "\'");
} if(System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
((InitializingBean)bean).afterPropertiesSet();
return null;
}
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet(); // 先是进行 InitializationBean 的初始化
}
} if(mbd != null) {
String initMethodName = mbd.getInitMethodName(); // 然后, 如果这个bean 存在 init 方法,并且如果它非InitializationBean且方法名非 aferPropertiesSet,并且这个bean不是外部管理的 ,,那么执行它。
if(initMethodName != null && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
this.invokeCustomInitMethod(beanName, bean, mbd);
}
} }

spring 之 init-method & InitializingBean的更多相关文章

  1. spring init method destroy method

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

  2. Spring报错: org.springframework.beans.factory.support.BeanDefinitionValidationException: Couldn't find an init method named 'init' on bean with name 'car'(待解答)

    在Spring工程里,有一个Car类的bean,Main.java主程序,MyBeanPostProcessor.java是Bean后置处理器. 文件目录结构如下: Car.java package ...

  3. MyBatis与Spring MVC结合时,使用DAO注入出现:Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required

    错误源自使用了这个例子:http://www.yihaomen.com/article/java/336.htm,如果运行时会出现如下错误: Invocation of init method fai ...

  4. Error creating bean with name 'sqlSessionFactory' defined in class path resource [config/spring/applicationContext.xml]: Invocation of init method failed;

    我报的错: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSes ...

  5. 003-Spring4 扩展分析-spring类初始化@PostConstruct > InitializingBean > init-method、ApplicationContext、BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

    一.spring类初始化@PostConstruct > InitializingBean > init-method InitializingBean接口为bean提供了初始化方法的方式 ...

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

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

  7. 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 ...

  8. Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Unable t

    spring与hibernate整合然后出现如下错误: org.springframework.beans.factory.BeanCreationException: Error creating ...

  9. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [bean.xml]: Invocation of init method failed; nested exception is

    在复制xml文件进行修改的时候,我经常将不小心对原文件进行修改,而导致创建bean出错.报错如下所示: Exception sending context initialized event to l ...

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

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

随机推荐

  1. VUE简单组件通信

    [x] 1.prop组件通信 1.简单理解 2.多层嵌套 [x] 2.使用ref进行组件通信 [x] 3.$emit组件通信 1.prop组件通信 1.简单理解 有点类似于应式的感觉,我不管你要不要只 ...

  2. ubantu 重启mysql

    如何启动/停止/重启MySQL一. 启动方式 1.使用 service 启动:service mysql start 2.使用 mysqld 脚本启动:/etc/inint.d/mysql start ...

  3. sysroot和prefix

    --with-sysroot用来指定系统的root.该选项主要用于新系统(比如LFS)构建或交叉编译.比如你的LFS的root在/mnt/lfs,那么configure时指定--with-sysroo ...

  4. Qt error: stray '\241' in program

    转载:iGoforward 报错的意思是c++中的产生了编译错误. 该错误是指源程序中有非法字符,需要将非法字符去掉.一般是由于编程者(不用程序员这个名词是因为这种错误太低级)使用中文输入法 或者从别 ...

  5. Javascript中的原型、原型链(十)

    一.原型 每当创建一个函数时,函数就会包含一个prototype属性,这个属性其实相当于一个指针,指向调用该构造函数创建的对象原型. 这个对象原型里面有一个constructor属性,这个属性又指向构 ...

  6. bzoj4812: [Ynoi2017]由乃打扑克

    由于查询的是树链的并的信息,同时信息不能高效合并,只能考虑用bitset维护,小范围暴力预处理以便从bitset算出答案 对树分块,保证每块是连通的且直径较小,对分出的块缩点建新树,在新树上建树上ST ...

  7. 关于java前端入门的一些简单的看法

    html:是网页的骨架,静态网页初步的轮廓,简单粗糙,僵硬又没有美感.表单的标签<form>,里面的<input>很常用,里面有type属性等css:为了更加灵活,常与div一 ...

  8. [UE4]判断UI动画播放方向

    使用一个变量来记录播放的方向.

  9. 2017湖湘杯复赛writeup

    2017湖湘杯复赛writeup 队伍名:China H.L.B 队伍同时在打 X-NUCA  和 湖湘杯的比赛,再加上周末周末周末啊,陪女朋友逛街吃饭看电影啊.所以精力有点分散,做出来部分题目,现在 ...

  10. sas 经验小结(1)

    1.重要的事情说三遍:在SAS中,对数据集操作要在OPTIONS中使用Compress=yes 能有效的降低文件的大小. 在SAS运行LOG中,可以看如下提示: NOTE: 压缩的数据集 T.PHON ...