Struts2 运行流程分析之Dispatcher初始化
Dispatcher 初始化
Disptcher的初始化方法
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
31
32
33
34
|
public class Dispatcher {
// 核心初始化方法
public void init() {
if (configurationManager == null) {
configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
try {
init_DefaultProperties(); // [1]
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
init_CustomConfigurationProviders(); // [5]
init_FilterInitParameters() ; // [6]
init_AliasStandardObjects() ; // [7]
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
} catch (Exception ex) {
if (LOG.isErrorEnabled())
LOG.error("Dispatcher initialization failed", ex);
throw new StrutsException(ex);
}
}
|
初始化 ConfigurationProvider, 将初始化的ConfigurationProvider添加到Dispatcher对象configurationManager属性中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// 初始化 DefaultPropertiesProvider
init_DefaultProperties(); // [1]
// 初始化 XmlConfigurationProvider 和 StrutsXmlConfigurationProvider,
// 用于解析 struts-default.xml,struts-plugin.xml,struts.xml
init_TraditionalXmlConfigurations(); // [2]
// 初始化LegacyPropertiesConfigurationProvider
init_LegacyStrutsProperties(); // [3]
// 初始化用户自定义的Provider,在<init-param> 中配置
init_CustomConfigurationProviders(); // [5]
// 将<init-param>配置数据添加到LocatableProperties对象中
init_FilterInitParameters() ; // [6]
// 初始化BeanSelectionProvider对象
init_AliasStandardObjects() ; // [7]
|
继续往下分析
1
2
3
4
5
6
7
8
9
10
|
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
|
init_PreloadConfiguration方法的代码实现:
1
2
3
4
5
6
7
8
9
|
private Container init_PreloadConfiguration() {
Configuration config = configurationManager.getConfiguration();
Container container = config.getContainer();
boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
LocalizedTextUtil.setReloadBundles(reloadi18n);
return container;
}
|
configurationManager.getConfiguration() 方法的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public synchronized Configuration getConfiguration() {
if (configuration == null) {
setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
try {
// 由于该方法实现复杂,特贴上实现代码,如下
configuration.reloadContainer(getContainerProviders());
} catch (ConfigurationException e) {
setConfiguration(null);
throw new ConfigurationException("Unable to load configuration.", e);
}
} else {
conditionalReload();
}
return configuration;
}
|
该方法里调用DefaultConfiguration对象的reloadContainer方法,该方法实现比较复杂,代码如下:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
packageContexts.clear();
loadedFileNames.clear();
List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
// 遍历所有的provider,依次这些Provider的init方法和register方法,
// 并将ContainerProperties对象和ContainerBuilder添加进去
for (final ContainerProvider containerProvider : providers)
{
containerProvider.init(this);
containerProvider.register(builder, props);
}
// 设置Constants
props.setConstants(builder);
// 构造了Factory对象为DefaultConfiguration
builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
});
// 获取一个上下文
ActionContext oldContext = ActionContext.getContext();
try {
// Set the bootstrap container for the purposes of factory creation
// 设置引导容器
// ObjectFactory、ReflectionProvider、ValueStackFactory、XWorkConverter
// TextProvider、ObjectTypeDeterminer、PropertyAccessor、OgnlUtil
Container bootstrap = createBootstrapContainer();
// 添加到context
setContext(bootstrap);
container = builder.create(false);
setContext(container);
objectFactory = container.getInstance(ObjectFactory.class);
// Process the configuration providers first
// 遍历所有Provider,注入到容器内
for (final ContainerProvider containerProvider : providers)
{
if (containerProvider instanceof PackageProvider) {
container.inject(containerProvider);
// 调用每个Provider的loadPackages,也就是加载所有的package节点,
// 具体可以看XmlConfigurationProvider类和StrutsXmlConfigurationProvider类的loadPackages方法实现
((PackageProvider)containerProvider).loadPackages();
packageProviders.add((PackageProvider)containerProvider);
}
}
// Then process any package providers from the plugins
Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
if (packageProviderNames != null) {
// 依次调用所有的PackageProvider的init方法和loadPackages方法
for (String name : packageProviderNames) {
PackageProvider provider = container.getInstance(PackageProvider.class, name);
provider.init(this);
provider.loadPackages();
packageProviders.add(provider);
}
}
// 重新构建配置
rebuildRuntimeConfiguration();
} finally {
if (oldContext == null) {
ActionContext.setContext(null);
}
}
// 返回所有package provider
return packageProviders;
}
|
从上面的代码分析得到该方法一共做了如下几件事:
- 调用了所有providers的init、register方法
- 初始化了Xwork框架的几个关键对象:ObjectFactory、ReflectionProvider、ValueStackFactory、XWorkConverter、TextProvider、ObjectTypeDeterminer、PropertyAccessor、OgnlUtil
- 将所有PackageProvider类型的Provider注入到容器内,并调用Provider的loadPackages方法,进行加载package节点的xml配置,具体可以看XmlConfigurationProvider类和StrutsXmlConfigurationProvider类的loadPackages方法实现
- 然后在依次调用所有PackageProvider类型的Provider的init方法和loadPackages
- 重新构建配置
- 返回所有package provider
分析到这里已经非常清楚了,我们回头在看 Dispatcher类的init_PreloadConfiguration方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
private Container init_PreloadConfiguration() {
// 获取DefaultConfiguration对象,调用所有Provider解析配置文件,注入到容器内
Configuration config = configurationManager.getConfiguration();
Container container = config.getContainer();
// 国际化处理
boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
LocalizedTextUtil.setReloadBundles(reloadi18n);
// 返回容器
return container;
}
|
我们已经搞清楚了init_PreloadConfiguration, 回去继续分析Dispatcher类的init方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 解析配置文件并构建容器
Container container = init_PreloadConfiguration();
container.inject(this);
// 获取struts.configuration.xml.reload配置,如果为true,则重新加载配置文件生成配置对象,一般在开发模式下使用,上线设置为false
init_CheckConfigurationReloading(container);
// 初始化weblogic相关配置, 对weblogic不了解 - -!
init_CheckWebLogicWorkaround(container);
// 用于用户自定义扩展Dispatcher
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
|
目前我们已经完成Dispatcher的初始化的简单分析,并没有对XmlConfigurationProvider类和StrutsXmlConfigurationProvider类详细分析.