前面分析了Dispatcher的init()方法中加载了各种配置文件配置器,并且根据配置文件创建了相应的ConfigurationProvider,各个ConfigurationProvider中的init(),register()方法在哪调用的呢?
首先介绍一下configuration和ConfigurationManager元素:
配置管理元素(configuration)作用:
(1)提供框架级对所有配置元素的访问操作接口
(2)对所有的配置元素进行初始化调度
ConfigurationManager是整个配置元素进行操作的代理接口类,而真正对所有配置元素的初始化进行调度的是Configuration对象.
配置元素的加载器:容器加载器(ContainerProvider)和事件映射加载器(PackageProvider)封装与ConfigurationManager内部,对真正的配置元素与配置元素加载器进行严格的分离,使得Configuration和configurationManager对象的职责划分更为清晰。
这里贴出一张分析到加载action标签流程图:
下面就慢慢来看吧,Dispatcher中init()方法中部分代码:
Container container = init_PreloadConfiguration(); container.inject(this);1、init_PreloadConfiguration() 代码:
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对象将初始化过程与元素调度过程和而为一的对象,主要目的是为了简化上层对象对配置调度的过程。不仅获得了Configuration对象,同时完成了对所有配置元素的调度。
通过配置管理器获得Configuration,具体怎么获得,请继续看
2、getConfiguration()代码:
/** * Get the current XWork configuration object. By default an instance of DefaultConfiguration will be returned * * @see com.opensymphony.xwork2.config.impl.DefaultConfiguration */ 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; }注释:configuration是com.opensymphony.xwork2.config.impl.DefaultConfiguration类型,如果 configuration为空,new DefaultConfiguration 新对象。
3、onfiguration.reloadContainer(getContainerProviders())代码:
首先解释一下reloadContainer传参ContainerProvider,而前面我们添加继承ConfigurationProvider,这2个类不一样啊?笔者看到这里,也疑惑了,没办法研究研究,看看类与类直接有什么联系?
public interface ConfigurationProvider extends ContainerProvider, PackageProvider { } 原来接口ConfigurationProvider 继承了ContainerProvider和PackageProvider
public synchronized ListreloadContainer(List providers) throws ConfigurationException {
//内部缓存对象的清理工作 packageContexts.clear(); loadedFileNames.clear(); ListpackageProviders = new ArrayList (); //初始化所有Properties文件中相关运行参数的主要操作对象 ContainerProperties props = new ContainerProperties(); ContainerBuilder builder = new ContainerBuilder(); for (final ContainerProvider containerProvider : providers) { containerProvider.init(this); containerProvider.register(builder, props);//循环调用ConfigurationProvider的init和register方法,明白了吧,在这里统一循环调用 } props.setConstants(builder); //注入依赖关系,在这里并不产生实例 builder.factory(Configuration.class, new Factory () { 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 Container bootstrap = createBootstrapContainer(); setContext(bootstrap);//create已经注入依赖关系的Container
container = builder.create(false);;//完成真真搞得容器初始化 setContext(container); objectFactory = container.getInstance(ObjectFactory.class); // Process the configuration providers first for (final ContainerProvider containerProvider : providers) { if (containerProvider instanceof PackageProvider) { container.inject(containerProvider); ((PackageProvider)containerProvider).loadPackages();//调用PackageProvider的loadPackages()方法,这里主要是针对XmlConfigurationProvider和StrutsXmlConfigurationProvider packageProviders.add((PackageProvider)containerProvider); } } // Then process any package providers from the plugins SetpackageProviderNames = container.getInstanceNames(PackageProvider.class); if (packageProviderNames != null) { for (String name : packageProviderNames) { PackageProvider provider = container.getInstance(PackageProvider.class, name); provider.init(this); provider.loadPackages(); packageProviders.add(provider); } }
对所有的packageConfig进行namespace级别的重新分类,这样做的目的在于当xwork框架相应http请求时可以根据namespace进行url匹配 rebuildRuntimeConfiguration(); } finally { if (oldContext == null) { ActionContext.setContext(null); } } return packageProviders; }注释:上面代码中 containerProvider.init(this);
containerProvider.register(builder, props);
loadPackages()方法我们在上一篇文章分析了,这就不再赘述。