關(guān)于在spring容器初始化 bean 和銷毀前所做的操作定義方式有三種:
和 @PreDestroy 方法 實(shí)現(xiàn)初始化和銷毀bean之前進(jìn)行的操作
[java]view plaincopy
import?javax.annotation.PostConstruct;????
import?javax.annotation.PreDestroy;????
public?class?DataInitializer{?????
@PostConstruct??
public?void?initMethod()?throws?Exception?{??
System.out.println("initMethod?被執(zhí)行");??
????}??
@PreDestroy??
public?void?destroyMethod()?throws?Exception?{??
System.out.println("destroyMethod?被執(zhí)行");??
????}??
}??
第二種是:通過(guò) 在xml中定義init-method 和 ?destory-method方法
[java]view plaincopy
public?class?DataInitializer{??
public?void?initMethod()?throws?Exception?{??
System.out.println("initMethod?被執(zhí)行");??
????}??
public?void?destroyMethod()?throws?Exception?{??
System.out.println("destroyMethod?被執(zhí)行");??
????}??
}??
[html]view plaincopy
??
第三種是:?通過(guò)bean實(shí)現(xiàn)InitializingBean和 DisposableBean接口
[java]view plaincopy
import?org.springframework.beans.factory.DisposableBean;??
public?class?DataInitializer?implements?InitializingBean,DisposableBean{??
@Override??
public?void?afterPropertiesSet()?throws?Exception?{??
System.out.println("afterPropertiesSet?被執(zhí)行");??
????}??
@Override??
public?void?destroy()?throws?Exception?{??
System.out.println("destroy?被執(zhí)行");??
????}??
}??
其中第一種和第二種是同一種形式,只不過(guò)一種xml配置,另外一種采用注解形式罷了,有很大區(qū)別的是第三種,
如果同一個(gè)bean同時(shí)采用兩種方式初始化的時(shí)候執(zhí)行某個(gè)方法,首先在執(zhí)行順序上就會(huì)體現(xiàn)出來(lái)。
先執(zhí)行afterPropertiesSet(),
后執(zhí)行initMethod()
這里我們看下源碼
這方式在spring中是怎么實(shí)現(xiàn)的?
通過(guò)查看spring的加載bean的源碼類(AbstractAutowireCapableBeanFactory)可看出其中奧妙
AbstractAutowireCapableBeanFactory類中的invokeInitMethods講解的非常清楚,源碼如下:
[java]view plaincopy
protected?void?invokeInitMethods(String?beanName,?final?Object?bean,?RootBeanDefinition?mbd)??
throws?Throwable?{??
//判斷該bean是否實(shí)現(xiàn)了實(shí)現(xiàn)了InitializingBean接口,如果實(shí)現(xiàn)了InitializingBean接口,則只掉調(diào)用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()?{??
public?Object?run()?throws?Exception?{??
//直接調(diào)用afterPropertiesSet??
??????????????????????((InitializingBean)?bean).afterPropertiesSet();??
return?null;??
??????????????????}??
??????????????},getAccessControlContext());??
}catch?(PrivilegedActionException?pae)?{??
throw?pae.getException();??
??????????}??
??????}??????????????????
else?{??
//直接調(diào)用afterPropertiesSet??
??????????((InitializingBean)?bean).afterPropertiesSet();??
??????}??
??}??
if?(mbd?!=?null)?{??
??????String?initMethodName?=?mbd.getInitMethodName();??
//判斷是否指定了init-method方法,如果指定了init-method方法,則再調(diào)用制定的init-method??
if?(initMethodName?!=?null?&&?!(isInitializingBean?&&?"afterPropertiesSet".equals(initMethodName))?&&??
??????????????!mbd.isExternallyManagedInitMethod(initMethodName))?{??
//進(jìn)一步查看該方法的源碼,可以發(fā)現(xiàn)init-method方法中指定的方法是通過(guò)反射實(shí)現(xiàn)??
??????????invokeCustomInitMethod(beanName,?bean,?mbd);??
??????}??
??}??
總結(jié):
1:spring為bean提供了兩種初始化bean的方式,實(shí)現(xiàn)InitializingBean接口,實(shí)現(xiàn)afterPropertiesSet方法,或者在配置文件中同過(guò)
init-method指定,兩種方式可以同時(shí)使用
2:實(shí)現(xiàn)InitializingBean接口是直接調(diào)用afterPropertiesSet方法,比通過(guò)反射調(diào)用init-method指定的方法效率相對(duì)來(lái)說(shuō)要高點(diǎn)。但是
init-method方式消除了對(duì)spring的依賴
3:如果調(diào)用afterPropertiesSet方法時(shí)出錯(cuò),則不調(diào)用init-method指定的方法。