spring 之 init-method & InitializingBean
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的更多相关文章
- spring init method destroy method
在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. ...
- 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 ...
- 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 ...
- 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 ...
- 003-Spring4 扩展分析-spring类初始化@PostConstruct > InitializingBean > init-method、ApplicationContext、BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
一.spring类初始化@PostConstruct > InitializingBean > init-method InitializingBean接口为bean提供了初始化方法的方式 ...
- java代码中init method和destroy method的三种使用方式
在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. ...
- 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 ...
- 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 ...
- 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 ...
- SSH项目练习的时候报错:[applicationContext.xml]: Invocation of init method failed;
这里是控制台的报错信息:org.springframework.beans.factory.BeanCreationException: Error creating bean with name ' ...
随机推荐
- 放一个Dynamicinputs corresponding to Dynamicknobs的Node源码
static const char* const CLASS = "AddInputsSol"; static const char* const HELP = "Add ...
- 部署Java Web项目到Heroku
1.在Heroku上创建一个新的App 2. 创建成功后添加对MYSQL的支持,点击find more add-ons 3. 这里我选择的是 JawsDB Mysql 4.添加成功后我们可以查看数据库 ...
- 【SQL Server】MS SQL Server中的CONVERT日期格式化大全
CONVERT 函数将某种数据类型的表达式显式转换为另一种数据类型.SQL Server中 将日期格式化. SQL Server 支持使用科威特算法的阿拉伯样式中的数据格式. 在表中,左侧的两列表示将 ...
- gmake缺失错误
原文:http://blog.csdn.net/syh_486_007/article/details/53862831 编译nachos程序的时候发现了这样一个错误gmake: command no ...
- 廖雪峰Java2面向对象编程-1面向对象-1面向对象基础
1.对象的概念 面向对象编程:Object-Oriented Programming 对现实世界建立计算机模型的一种编程方法. 现实世界 计算机模型 Java代码 人 类/class class Pe ...
- openstack处理booting from hard disk
当你的实例启动出现如下报错的处理方式: 需要编辑/etc/nova/nova.conf [libvirt] cpu_mode = none virt_type=qemu 修改后需要 ...
- [UE4]RetainerBox,控制UI更新频率,把渲染后的UI当成Texture
RetainerBox是一个容器,只会影响其容器内的UI,RetainerBox的作用: 一.控制UI更新频率(可能是为有优化性能) 1.在UserWidget中添加Retainer Box容器,并在 ...
- [UE4]碰撞机制
应用于两种情况: 一.射线追踪,LineTrace 1.射线来自某个Trace Channel 2.Trace Channel 默认有两个:Visibility(不是可见的意思.只是Channel名称 ...
- Vue百度搜索
<!DOCTYPE html><html lang="en"><head> <meta charset="GBK"&g ...
- Shiro Realm
Realm: 在实际应用中,shiro从数据库中获取安全数据(如用户.角色.权限),而不是从ini中,可作为安全数据源 即SecurityManager要验证用户身份,那么它需要从Realm获取相应的 ...