spring初始化接口InitializingBean
InitializingBean接口用於初始化bean。此接口只有一個方法afterPropertiesSet,
繼承此接口的bean,在bean的屬性初始化會執行這個方法。
下面看一下此接口定義
/**
* 當需要在BeanFactory設置完bean的所有屬性後,還需做一些初始化的操作,可讓該bean實現此接口
*/
public interface InitializingBean {
/**
* 由BeanFactory在設置完bean的屬性後調用
* 該方法可用於實現bean的初始化操作,不過需要在bean的屬性設置完畢後(從名字也可以看出)
*/
void afterPropertiesSet() throws Exception;
}
我們可以在 AbstractAutowireCapableBeanFactory
類中找到此接口的調用位置,如下:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//是否實現了 InitializingBean 接口
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((PrivilegedExceptionAction<Object>) () -> {
// 調用該方法
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 調用該初始化方法
((InitializingBean) bean).afterPropertiesSet();
}
}
// 判斷是否指定了init-method方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 執行init-method 方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
spring還有一種初始化方式,指定 init-method 方法,如xml配置的bean
<bean id="initAndDestroySeqBean" class="com.wthfeng.dubboapi.beans.InitAndDestroyBean" init-method="initMethod"
destroy-method="destroyMethod"/>
從源碼分析可知,init-method的初始化方法在InitializingBean.afterPropertiesSet 方式之後。
總結如下:
- spring有兩種初始化bean的方式,實現InitializingBean接口以及配置init-method方法,兩種方式可以同時使用,實現接口的方式比指定init-method先調用。
- 如果調用afterPropertiesSet方法時出錯,則不調用init-method指定的方法。