Spring中初始化bean和销毁bean的时候执行某个方法的详解
2015-12-03 12:57
603 查看
第一种:通过注解@PostConstruct
和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class DataInitializer{
@PostConstruct
public void initMethod() throws Exception {
System.out.println("initMethod 被执行");
}
@PreDestroy
public void destroyMethod() throws Exception {
System.out.println("destroyMethod 被执行");
}
}
第二种是:通过 在xml中定义init-method 和 destory-method方法
public class DataInitializer{
public void initMethod() throws Exception {
System.out.println("initMethod 被执行");
}
public void destroyMethod() throws Exception {
System.out.println("destroyMethod 被执行");
}
}
<bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/>
第三种是: 通过bean实现InitializingBean和 DisposableBean接口
import org.springframework.beans.factory.DisposableBean;
public class DataInitializer implements InitializingBean,DisposableBean{
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet 被执行");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy 被执行");
}
其中第一种和第二种是同一种形式,只不过一种xml配置,另外一种采用注解形式罢了,有很大区别的是第三种,
如果同一个bean同时采用两种方式初始化的时候执行某个方法,首先在执行顺序上就会体现出来。
先执行
afterPropertiesSet(),
后执行
initMethod()
这里我们看下源码
这方式在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);
}
}
}
总结:
spring为bean提供了两种初始化bean的方式,实现
InitializingBean接口,实现
afterPropertiesSet方法,或者在配置文件中同过
init-method指定,两种方式可以同时使用。
实现
InitializingBean接口是直接调用
afterPropertiesSet方法,比通过反射调用
init-method指定的方法效率相对来说要高点。但是
init-method方式消除了对spring的依赖。
如果调用
afterPropertiesSet方法时出错,则不调用
init-method指定的方法。
相关文章推荐
- java反射
- 为什么Maven会更改Eclipse JDK设置
- Java中Map的遍历
- Unsupported major.minor version (jdk版本错误)解决方案 办法
- java正则表达式
- 百度地图相关(1)百度地图的首次默认加载
- Eclipse不给提示no default proposals
- spring之BeanFactoryAware接口
- springMVC第一课:配置
- Eclipse的Android xml预览布局时,超出屏幕怎么看效果
- 狗屎的Java规范
- 个人学习java的真实经验!
- Java并发编程:Lock
- java:从消息机制谈到观察者模式
- 定时任务中的 Timer的schedule和scheduleAtFixedRate方法的区别
- RxJava的简单学习(学习自扔物线)
- Java并发编程:volatile关键字解析
- javaday2-java语言基础
- Java反射机制详解
- java中String的常用方法