目录
  1. 前言
  2. configureAndRefreshWebApplicationContext方法
  3. determineContextInitializerClasses方法
  4. customizeContext方法
  5. refresh方法
spring(1) web应用中spring IOC容器初始化(1)

前言

springMVC(12) ContextLoaderListener中我们有遇到一个方法configureAndRefreshWebApplicationContext,这个方法就是用来做spring IOC容器初始化操作的。

configureAndRefreshWebApplicationContext方法

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
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
// 如果WebApplicationContext的id仍然设置为它的原始默认值,则将其改为包含有效信息的更有用的值
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
wac.setId(idParam);
}
else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()));
}
}

wac.setServletContext(sc); // 设置WebApplicationContext的servletContext
// 设置配置文件路径
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}

// 设置配置环境属性源
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}

customizeContext(sc, wac); // 执行自定义的初始化类(下面会分析)
wac.refresh(); // 初始化spring IoC容器
}

determineContextInitializerClasses方法

由于customizeContext中调用了determineContextInitializerClasses,于是我们此处先看determineContextInitializerClasses方法的源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
}

这个方法主要是用来获取初始化类的,这些类均继承这样一个接口,

1
2
3
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}

我们可以通过继承这个接口来进行写自己的初始化类,并且进行相应配置,关于这部分的作用可以参考如下文章http://blog.csdn.net/qingxiutianya/article/details/51735741

customizeContext方法

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
protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =
determineContextInitializerClasses(sc);

// 如果没有自定义的初始化类,则什么都不做
if (initializerClasses.isEmpty()) {
return;
}

ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances =
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();

for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {
Class<?> initializerContextClass =
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
if (initializerContextClass != null) {
Assert.isAssignable(initializerContextClass, wac.getClass(), String.format(
"Could not add 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()));
}
initializerInstances.add(BeanUtils.instantiateClass(initializerClass));
}

AnnotationAwareOrderComparator.sort(initializerInstances);
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : initializerInstances) {
initializer.initialize(wac);
}
}

如果清楚了initializerClasses是个怎么的东西之后,我们可以很清楚地知道这个方法的作用,就是执行自己定制的初始化类。

refresh方法

这个方法才是最后真正用来初始化spring IoC容器的。

这个方法是WebApplicationContext的。由于默认的WebApplicationContext是XmlWebApplicationContext,我们就接着来看XmlWebApplicationContext中实现。感觉可能有点长,另开一章吧。
spring(2) web应用中spring IOC容器初始化(2)

文章作者: 谷河
文章链接: https://www.lyytaw.com/spring/spring_web_ioc_init_1/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 谷河|BLOG