ConfigurationManager部分

Wiki地址:http://wiki.opensymphony.com/display/XW/XWork+Configurations
按文档所说,这是XWork配置的核心

这部分很复杂,比较担心自己看错了什么,所以这篇日志极有可能出现技术上的错误。
还是试着把自己读到的部分写出来,就算出错,如果有人愿意批的话就赚到了。

应用启动之后,装载配置项是通过调用DefaultConfiguration.reloadContainer(List providers)来做的。
此方法的前几行代码:

        ContainerProperties props = new ContainerProperties();
        ContainerBuilder builder = new ContainerBuilder();
        for (final ContainerProvider containerProvider : providers)
        {
            containerProvider.init(this);
            containerProvider.register(builder, props);
        }
        props.setConstants(builder);

ContainerProperties先简单的理解为继承自java.util.Properties的一个类吧。然后new了一个ContainerBuilder出来。接着在for循环里让每一个ContainerProvider都init一遍。

都以XmlConfigurationProvider为例查看
XmlConfigurationProvider.init(Configuration)中的代码前面看过,它就是去做loadDocuments(xmlConfigurationFiles)的事情,然后就是装载文件里定义的种种bean了。
XmlConfigurationProvider.register(ContainerBuilder, ContainerProperties)的工作,是解析[系统、用户]的配置文件,在Struts2中,它会解析struts-default.xml、struts-plugin.xml、struts.xml。
ContainerBuilder对象用于创建上述配置文件中的bean,这些bean位于

<struts>
  <bean class="" type="" name=""/>
  ...
  <bean class="" type="" name=""/>
</struts>

当中,可以查看struts-default.xml文件,这些bean都是XWork自带的一些核心类了,前面提过的SpringObjectFactory创建bean,都是建Action相关的客户自定义bean,也就是说XWork的对象创建工作,并没有全部转交给Spring去做。
ContainerProperties对象在此用于保存上述配置文件中的constant部分的key-value。

再看XWorkConfigurationProvider
它的init(Configuration)方法不做任何事
而register.register(ContainerBuilder, ContainerProperties)的工作,疯狂的调用了ContainerBuilder.factory(xxx).factory(xxx).xxx.factory(xxx),最后也往ContainerProperties对象里塞了点东西。
这一堆的factory方法,跟XmlConfigurationProvider里面的调用有一些重复(对比代码和配置文件)。
跟踪factory方法,最后找到 Object com.opensymphony.xwork2.inject.ContainerImpl.ConstructorInjector.construct(InternalContext context, Class< ? super T> expectedType) 方法,这个方法记录了进入过的class,也就是做了一个映像,避免重复对一些类进行操作。所以上面的重复是没有影响的。此方法准备好了一系列针对每一个class的工厂,后续的核心对象创建,都被它接手了。

props.setConstants(builder); 此调用把一些常量也进行了对应类的转换,然后把相应的类放进了factory方法。

回头看reloadContainer方法,接下去的try-finally,一开始把本线程的一些信息装进了ActionContext,然后:

// Process the configuration providers first
for (final ContainerProvider containerProvider : providers){
  if (containerProvider instanceof PackageProvider) {
    container.inject(containerProvider);
    ((PackageProvider)containerProvider).loadPackages();
    packageProviders.add((PackageProvider)containerProvider);
  }
}

// Then process any package providers from the plugins
Set packageProviderNames = 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);
  }
}
rebuildRuntimeConfiguration();

把PackageProvider装进系统Container,并让它开始干活,做的是init(Container)和loadPackages()。
rebuildRuntimeConfiguration()配置具体的Action。
然后Container就对外提供服务了。

这里它把配置的加载、解析分开了。很灵活,只是我这个凡夫俗子觉得好像没这个必要,本来就是对一组对象进行操作,那给一个包关起门来做,完了给出结果就是了。

方法的 finally 部分把当前线程的ActionContext置空,完成。

在这部分,XWork抽象了ConfigurationProvider,使得体系可以接收不同的Provider,这极大的增强了可应用性。


PS@2010-12-10
引用一张 struts2 的框架图(时间太长,我应该没在之前帖上来过吧。。。),原地址是http://www.blogjava.net/images/blogjava_net/myyate/15.PNG
这张图画得比javaeye以及xwork的wiki上的那个,要准确一些:

anyShare分享到:
          

没准儿您会对以下内容感兴趣: