關(guān)于在spring 容器初始化 bean 和銷毀前所做的操作定義方式有三種:
第一種:通過(guò)注解@PostConstruct 和 @PreDestroy 方法 實(shí)現(xiàn)初始化和銷毀bean之前進(jìn)行的操作
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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方法
1
2
3
4
5
6
7
8
|
public class DataInitializer{ public void initMethod() throws Exception { System.out.println( "initMethod 被執(zhí)行" ); } public void destroyMethod() throws Exception { System.out.println( "destroyMethod 被執(zhí)行" ); } } |
<bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/>
第三種是: 通過(guò)bean實(shí)現(xiàn)InitializingBean和 DisposableBean接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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講解的非常清楚,源碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
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<Object>() { 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指定的方法。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://blog.csdn.net/aa2484219/article/details/51261227