Spring Context初期化プロセス(ソース分析)
XML構成のContextでもSpring BootのContextでもWebサービスのContextでも作成後にAbstractApplicationContextクラスのrefresh()メソッドが呼び出されます.
AbstraactApplicationContextの下にあるrefresh()メソッドにナビゲートし、解析を開始します.全体の流れは以下の通りです.
14ステップに分けて、次は一歩一歩分析します.
1.synchronized(this.startupShutdownMonitor)をロックし、同じ時間にstartupShutdownMonitorの状態が変化しないことを確認します.2.prepareRefresh()はリフレッシュの準備をして、メソッドの表示に入ります.
3.内部のBean Factoryを更新して取得する
4.アクセス方法prepareBeanFactory()
クラス・ローダとバックグラウンド・プロセッサの設定、自動アセンブリを行わないタイプの構成、デフォルトの環境Beanの登録など、BeanFactoryの準備を行います.
5.postProcessBeanFactoryメソッドのソースコードは次のとおりです.
ContextのサブクラスにBeanFactoryを後処理する拡張機能を提供します.サブクラスがBean定義のロードが完了した後、コンテキストの初期化を開始する前にいくつかの特殊な論理を行う場合は、この方法を複写できます.
6.invokeBeanFactoryPostProcessors()メソッドのソースコードは次のとおりです.
Contextに登録されているBean Factory接尾辞プロセッサを実行します.ここでは、Beanを登録できる接尾辞プロセッサと、BeanFactoryを処理する接尾辞プロセッサの2種類があります.実行の順序は、登録可能なBeanのプロセッサを優先度で実行し、BeanFactoryのプロセッサを優先度で実行することです.O r f i g u r ationClassPostProcessorによってトリガーされ、ClassPathBeanDefinitionScannerによってBeanFactoryに解析されて登録されます.
7.registerBeanPostProcessorsメソッドのソースコードは次のとおりです.
Beanの接尾辞プロセッサを優先順位指定順にBeanFactoryに登録し、Beanの初期化前、後に処理を実行できます.
8.initMessageSourceメソッドのソースコードは次のとおりです.
メッセージの国際化をサポートするメッセージ・ソースの初期化
9.
アプリケーションイベントブロードキャストを初期化します.イベント・ブロードキャストは、様々なアプリケーションによって生成されたイベントをApplicationListenerに通知するために使用され、標準的なオブザーバ・モードである.
10.onRefreshメソッドのソースコードは次のとおりです.
は、特定のContextサブクラスを他のBeanに初期化するための拡張ステップです.
11.registerListenersメソッドのソースコードは次のとおりです.
ApplicationListenerを実現したBeanをイベント・ブロードキャストに登録し,ブロードキャストにおける早期の未ブロードキャスト・イベントを通知する.
12.finishBeanFactoryInitializationメソッドのソースコードは次のとおりです.
すべてのBean記述情報の変更をフリーズし、非遅延ロードの一例Beanをインスタンス化します.
13.finishRefreshメソッドのソースコードは次のとおりです.
コンテキストのリフレッシュを完了し、LifecycleProcessorのonFresh()メソッドを呼び出し、ContextRefreshedEventイベントをパブリッシュします.
14.
ReflectionUtilsのキャッシュ、AnnotationUtils、ResolvableTypeのキャッシュなど、共通のキャッシュをリセットします.
これで文章は終わりです.
AbstraactApplicationContextの下にあるrefresh()メソッドにナビゲートし、解析を開始します.全体の流れは以下の通りです.
@Override
public void refresh() throws BeansException, IllegalStateException {
//1
synchronized (this.startupShutdownMonitor) {
//2
prepareRefresh();
//3
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//4
prepareBeanFactory(beanFactory);
try {
//5
postProcessBeanFactory(beanFactory);
//6
invokeBeanFactoryPostProcessors(beanFactory);
//7
registerBeanPostProcessors(beanFactory);
//8
initMessageSource();
//9
initApplicationEventMulticaster();
//10
onRefresh();
//11
registerListeners();
// 12
finishBeanFactoryInitialization(beanFactory);
// 13
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
//14
resetCommonCaches();
}
}
}
14ステップに分けて、次は一歩一歩分析します.
1.synchronized(this.startupShutdownMonitor)をロックし、同じ時間にstartupShutdownMonitorの状態が変化しないことを確認します.2.prepareRefresh()はリフレッシュの準備をして、メソッドの表示に入ります.
/**
* ,
*/
protected void prepareRefresh() {
//
this.startupDate = System.currentTimeMillis();
//
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Context
initPropertySources();
// , properties
getEnvironment().validateRequiredProperties();
// ApplicationListeners
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// 。
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// ApplicationEvent
this.earlyApplicationEvents = new LinkedHashSet<>();
}
3.内部のBean Factoryを更新して取得する
4.アクセス方法prepareBeanFactory()
/**
* , ClassLoader
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// bean
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Bean
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
//BeanFactory
//MessageSource Bean( )
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// bean ApplicationListeners。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// LoadTimeWeaver ( )
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// ClassLoader 。
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
クラス・ローダとバックグラウンド・プロセッサの設定、自動アセンブリを行わないタイプの構成、デフォルトの環境Beanの登録など、BeanFactoryの準備を行います.
5.postProcessBeanFactoryメソッドのソースコードは次のとおりです.
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for registering special
* BeanPostProcessors etc in certain ApplicationContext implementations.
* @param beanFactory the bean factory used by the application context
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
ContextのサブクラスにBeanFactoryを後処理する拡張機能を提供します.サブクラスがBean定義のロードが完了した後、コンテキストの初期化を開始する前にいくつかの特殊な論理を行う場合は、この方法を複写できます.
6.invokeBeanFactoryPostProcessors()メソッドのソースコードは次のとおりです.
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// Bean Bean ( Bean )
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
Contextに登録されているBean Factory接尾辞プロセッサを実行します.ここでは、Beanを登録できる接尾辞プロセッサと、BeanFactoryを処理する接尾辞プロセッサの2種類があります.実行の順序は、登録可能なBeanのプロセッサを優先度で実行し、BeanFactoryのプロセッサを優先度で実行することです.O r f i g u r ationClassPostProcessorによってトリガーされ、ClassPathBeanDefinitionScannerによってBeanFactoryに解析されて登録されます.
7.registerBeanPostProcessorsメソッドのソースコードは次のとおりです.
/**
* Instantiate and register all BeanPostProcessor beans,
* respecting explicit order if given.
* Must be called before any instantiation of application beans.
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
Beanの接尾辞プロセッサを優先順位指定順にBeanFactoryに登録し、Beanの初期化前、後に処理を実行できます.
8.initMessageSourceメソッドのソースコードは次のとおりです.
/**
*
* ,
*/
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
メッセージの国際化をサポートするメッセージ・ソースの初期化
9.
/**
*
*
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
アプリケーションイベントブロードキャストを初期化します.イベント・ブロードキャストは、様々なアプリケーションによって生成されたイベントをApplicationListenerに通知するために使用され、標準的なオブザーバ・モードである.
10.onRefreshメソッドのソースコードは次のとおりです.
/**
* Template method which can be overridden to add context-specific refresh work.
* Called on initialization of special beans, before instantiation of singletons.
* This implementation is empty.
* @throws BeansException in case of errors
* @see #refresh()
*/
protected void onRefresh() throws BeansException {
// : 。
}
は、特定のContextサブクラスを他のBeanに初期化するための拡張ステップです.
11.registerListenersメソッドのソースコードは次のとおりです.
/**
* ApplicationListener bean
* , bean.
*/
protected void registerListeners() {
//
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// FactoryBeans: bean
// , !
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// ,
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
ApplicationListenerを実現したBeanをイベント・ブロードキャストに登録し,ブロードキャストにおける早期の未ブロードキャスト・イベントを通知する.
12.finishBeanFactoryInitializationメソッドのソースコードは次のとおりです.
/**
* Bean
* beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// bean ( PropertyPlaceholderConfigurer bean) , :
// , 。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// LoadTimeWeaverAware Bean, 。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// ClassLoader 。
beanFactory.setTempClassLoader(null);
// bean , 。
beanFactory.freezeConfiguration();
// ( ) 。
beanFactory.preInstantiateSingletons();
}
すべてのBean記述情報の変更をフリーズし、非遅延ロードの一例Beanをインスタンス化します.
13.finishRefreshメソッドのソースコードは次のとおりです.
/**
* , LifecycleProcessor onRefresh()
* {@link org.springframework.context.event.ContextRefreshedEvent}.
*/
protected void finishRefresh() {
// ( ASM )。
clearResourceCaches();
// 。
initLifecycleProcessor();
// 。
getLifecycleProcessor().onRefresh();
// 。
publishEvent(new ContextRefreshedEvent(this));
// , LiveBeansView MBean。
LiveBeansView.registerApplicationContext(this);
}
コンテキストのリフレッシュを完了し、LifecycleProcessorのonFresh()メソッドを呼び出し、ContextRefreshedEventイベントをパブリッシュします.
14.
/**
* Reset Spring's common reflection metadata caches, in particular the
* {@link ReflectionUtils}, {@link AnnotationUtils}, {@link ResolvableType}
* and {@link CachedIntrospectionResults} caches.
* @since 4.2
* @see ReflectionUtils#clearCache()
* @see AnnotationUtils#clearCache()
* @see ResolvableType#clearCache()
* @see CachedIntrospectionResults#clearClassLoader(ClassLoader)
*/
protected void resetCommonCaches() {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
ReflectionUtilsのキャッシュ、AnnotationUtils、ResolvableTypeのキャッシュなど、共通のキャッシュをリセットします.
これで文章は終わりです.