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;
    }

从上面的代码分析得到该方法一共做了如下几件事:

  1. 调用了所有providers的init、register方法
  2. 初始化了Xwork框架的几个关键对象:ObjectFactory、ReflectionProvider、ValueStackFactory、XWorkConverter、TextProvider、ObjectTypeDeterminer、PropertyAccessor、OgnlUtil
  3. 将所有PackageProvider类型的Provider注入到容器内,并调用Provider的loadPackages方法,进行加载package节点的xml配置,具体可以看XmlConfigurationProvider类和StrutsXmlConfigurationProvider类的loadPackages方法实现
  4. 然后在依次调用所有PackageProvider类型的Provider的init方法和loadPackages
  5. 重新构建配置
  6. 返回所有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类详细分析.