Spring beanイニシャル順序
19184 ワード
InitializingBen,init-methodとPostConstruct
1、概要
インタフェースの名前から分かりますが、InitializingBeanの役割はbean初期化後に固定化された操作を行うことです.
Spring容器の中のBeanはライフサイクルがあり、SpringはBeanが初期化された後及びBeanが破壊される前に特定の操作を行うことができます.一般的な設定は以下の3つがあります.は、初期化後/廃棄前の動作方法を、InitializingBean/Dispable Beanインターフェースを実現することによってカスタマイズする. 要素のinit-method/destroy-method属性によって初期化後/廃棄前に呼び出す操作方法を指定します. は、指定された方法に@PostCostructまたは@Predestroy注釈を加えて、この方法を初期化または廃棄の前に呼び出すかを定式化する. 2、InitializingBen vs init-method
インターフェースの定義は以下の通りです. springはbeanを初期化する2つの方法を提供し、InitializingBenインターフェースを実現し、afterProptiesset方法を実現し、または構成ファイルにinit-methodで指定し、2つの方法は を同時に使用することができる.によりInitializingBenインターフェースを実現することは、afterPropertiessetメソッドを直接起動することであり、反射によってinit-methodに指定された方法よりも効率が高い.しかし、init-method方式は、springに対する依存性を解消する .一旦afterPropertiessetを呼び出し、init-method方法を実行し、afterPropertiesset方法を起動するとエラーが発生したら、init-method指定の方法を起動しない .
3、@PostConstruct
debugと呼び出しスタックを通して、クラスInit DestroyAnnotationBeanPostProcessorを見つけました.その中の核心方法、つまり@PostConstruct方法で呼び出された入口:
4、まとめ spring beanの初期化実行順序:構造方法-->@PostContstruct注釈の方法-->afterPropertiesset方法-->init-method指定の方法.具体的には例 を参照することができる. afterPropertiessetは、インターフェースを通じて(効率的に)呼び出されます.@PostConstructとinit-methodは、反射機構によって呼び出されます.
同じように、bean破壊プロセスの順序は:@Presdestroy>Displable Bean>destroy-methodはもう展開しません.ソースを見ればいいです.
テストコードは以下の通りです.
1、概要
インタフェースの名前から分かりますが、InitializingBeanの役割はbean初期化後に固定化された操作を行うことです.
Spring容器の中のBeanはライフサイクルがあり、SpringはBeanが初期化された後及びBeanが破壊される前に特定の操作を行うことができます.一般的な設定は以下の3つがあります.
インターフェースの定義は以下の通りです.
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
インターフェースは一つの方法しかないafterPropertiessetです.この方法の呼び出しの入り口はspring beanのAbstractAutowireCable BenFactoryをロードする責任があります.ソースは以下の通りです.protected void invokeInitMethods(String beanName, 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 + "'");
}
// afterPropertiesSet()
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(
new PrivilegedExceptionAction(bean) {
public Object run() throws Exception {
((InitializingBean) this.val$bean)
.afterPropertiesSet();
return null;
}
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// InitMethod()
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if ((initMethodName == null)
|| ((isInitializingBean) && ("afterPropertiesSet"
.equals(initMethodName)))
|| (mbd.isExternallyManagedInitMethod(initMethodName)))
return;
invokeCustomInitMethod(beanName, bean, mbd);
}
}
このソースから以下の結論が得られます.3、@PostConstruct
debugと呼び出しスタックを通して、クラスInit DestroyAnnotationBeanPostProcessorを見つけました.その中の核心方法、つまり@PostConstruct方法で呼び出された入口:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
名前から私たちはいくつかの情報を得ることができます.これはBeanPostProcessorです.BenPostProcessorのpostProcess BeforeInitializationは、Beanライフサイクルの中でafterPropertiessetとinit-methodの前に呼び出される.またフォローアップにより、@PostCostructメソッドの呼び出しも反射機構により行われます.4、まとめ
同じように、bean破壊プロセスの順序は:@Presdestroy>Displable Bean>destroy-methodはもう展開しません.ソースを見ればいいです.
テストコードは以下の通りです.
@Slf4j
public class InitSequenceBean implements InitializingBean {
public InitSequenceBean() {
log.info("InitSequenceBean: construct");
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("InitSequenceBean: afterPropertiesSet");
}
@PostConstruct
public void postConstruct() {
log.info("InitSequenceBean: postConstruct");
}
public void initMethod() {
log.info("InitSequenceBean: initMethod");
}
}
@Configuration
public class SystemConfig {
@Bean(initMethod = "initMethod", name = "initSequenceBean")
public InitSequenceBean initSequenceBean() {
return new InitSequenceBean();
}
}
@Slf4j
public class InitSequenceBeanTest extends ApplicationTests {
@Autowired
private InitSequenceBean initSequenceBean;
@Test
public void initSequenceBeanTest() {
log.info("Finish: {}", initSequenceBean.toString());
}
}