ApplicationContextInitializer机制
Posted 恒奇恒毅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ApplicationContextInitializer机制相关的知识,希望对你有一定的参考价值。
定义
/**
* Callback interface for initializing a Spring @link ConfigurableApplicationContext
* prior to being @linkplain ConfigurableApplicationContext#refresh() refreshed.
*
* <p>Typically used within web applications that require some programmatic initialization
* of the application context. For example, registering property sources or activating
* profiles against the @linkplain ConfigurableApplicationContext#getEnvironment()
* context's environment. See @code ContextLoader and @code FrameworkServlet support
* for declaring a "contextInitializerClasses" context-param and init-param, respectively.
*
* <p>@code ApplicationContextInitializer processors are encouraged to detect
* whether Spring's @link org.springframework.core.Ordered Ordered interface has been
* implemented or if the @@link org.springframework.core.annotation.Order Order
* annotation is present and to sort instances accordingly if so prior to invocation.
*
* @author Chris Beams
* @since 3.1
* @see org.springframework.web.context.ContextLoader#customizeContext
* @see org.springframework.web.context.ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM
* @see org.springframework.web.servlet.FrameworkServlet#setContextInitializerClasses
* @see org.springframework.web.servlet.FrameworkServlet#applyInitializers
*/
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext>
/**
* Initialize the given application context.
* @param applicationContext the application to configure
*/
void initialize(C applicationContext);
ApplicationContextInitializer
提供了对ConfigurableApplicationContext
初始化配置的能力。属于一个回调接口,主要用在web环境中,比如初始化property sources或者active profiles。
在哪儿调用?
ContextLoader
中
在ContextLoaderListener
的父类ContextLoader
#customizeContext方法中
protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac)
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =
determineContextInitializerClasses(sc);
for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses)
Class<?> initializerContextClass =
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
if (initializerContextClass != null && !initializerContextClass.isInstance(wac))
throw new ApplicationContextException(String.format(
"Could not apply context initializer [%s] since its generic parameter [%s] " +
"is not assignable from the type of application context used by this " +
"context loader: [%s]", initializerClass.getName(), initializerContextClass.getName(),
wac.getClass().getName()));
this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass));
AnnotationAwareOrderComparator.sort(this.contextInitializers);
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers)
initializer.initialize(wac);
protected List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>
determineContextInitializerClasses(ServletContext servletContext)
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> classes =
new ArrayList<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>();
String globalClassNames = servletContext.getInitParameter(GLOBAL_INITIALIZER_CLASSES_PARAM);
if (globalClassNames != null)
for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS))
classes.add(loadInitializerClass(className));
String localClassNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);
if (localClassNames != null)
for (String className : StringUtils.tokenizeToStringArray(localClassNames, INIT_PARAM_DELIMITERS))
classes.add(loadInitializerClass(className));
return classes;
从ServletContext
的初始化参数globalInitializerClasses、contextInitializerClasse获取。
-
DelegatingApplicationContextInitializer
该类代理了其他ApplicationContextInitializer
,它从ConfigurableApplicationContext
的环境变量context.initializer.classes中获取其他的ApplicationContextInitializer
。而DelegatingApplicationContextInitializer
已经定义在了spring.factories中,说明我们可以直接往context设置环境变量context.initializer.classes即可。 -
FrameworkServlet
org.springframework.web.servlet.FrameworkServlet#configureAndRefreshWebApplicationContext,逻辑跟ContextLoader
一致。 -
SpringApplication
org.springframework.boot.SpringApplication#applyInitializers方法中通过spring.factories机制获取实例,再调用方法。
以上是关于ApplicationContextInitializer机制的主要内容,如果未能解决你的问题,请参考以下文章