Struts2源码阅读(四)_Dispatcher&ConfigurationProvider续

本文详细解析了Struts2框架启动时配置加载的过程,包括默认配置提供者DefaultPropertiesProvider和遗留配置提供者LegacyPropertiesConfigurationProvider的区别,以及如何通过web.xml自定义配置提供者。
接下来第三步:init_LegacyStrutsProperties()
调用的是调用的是LegacyPropertiesConfigurationProvider
通过比较前面DefaultPropertiesProvider与调用的是LegacyPropertiesConfigurationProvider.
发现DefaultPropertiesProvider继承自后者,但重写了register()方法,主要是生成PropertiesSetting的不同,前者是根据org/apache/struts2/default.properties
后者是根据struts.properties

我们展开register()中的Settings.getInstance(),最后是调用getDefaultInstance()

private static Settings getDefaultInstance() {     
     if (defaultImpl == null) {     
         // Create bootstrap implementation     
//不带参数的DefaultSettings(),区别与DefaultPropertiesProvider中直接带default.properties参数     
//不带参数就是默认为struts.propertes,并且加载struts.custom.properties所定义的properties文件     
         defaultImpl = new DefaultSettings();     
    
         // Create default implementation     
         try {     
    //STRUTS_CONFIGURATION为:struts.configuration     
    //在struts.proterties中查找struts.configuration的值,这个值必须是org.apache.struts2.config.Configuration接口的实现类     
    //所以我有个困惑就是在下面的转换当中怎么将Configuration转换成Setting类型的...     
    //这一点先放下了,有时间再研究     
             String className = get(StrutsConstants.STRUTS_CONFIGURATION);     
    
             if (!className.equals(defaultImpl.getClass().getName())) {     
                 try {     
                     // singleton instances shouldn't be built accessing request or session-specific context data     
                     defaultImpl = (Settings) ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLoader().loadClass(className), null);     
                 } catch (Exception e) {     
                     LOG.error("Settings: Could not instantiate the struts.configuration object, substituting the default implementation.", e);     
                 }     
             }     
         } catch (IllegalArgumentException ex) {     
             // ignore     
  }  

在2.1.6中去掉了第四步:init_ZeroConfiguration(); 
第五步是自定义的configProviders

private void init_CustomConfigurationProviders() {     
    //从这里可以看到可以将自定义的Provider定义在web.xml中FilterDispatcher的param中:configProviders     
    String configProvs = initParams.get("configProviders");     
    if (configProvs != null) {     
        String[] classes = configProvs.split("//s*[,]//s*");     
        for (String cname : classes) {     
            try {     
                Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());     
                ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();     
                configurationManager.addConfigurationProvider(prov);     
            }      
...     
        }     
    }     
}   
第六步:init_FilterInitParameters

//从这里可以看出struts.properties中的属性不仅可以在struts.xml中以constant形式定义,而且可以在FilterDispatcher的param中定义       
    private void init_FilterInitParameters() {     
        configurationManager.addConfigurationProvider(new ConfigurationProvider() {     
            public void destroy() {}     
            public void init(Configuration configuration) throws ConfigurationException {}     
            public void loadPackages() throws ConfigurationException {}     
            public boolean needsReload() { return false; }     
    
            public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {     
                props.putAll(initParams);//在这里实现滴~     
            }     
        });     
    }  
第七步:init_AliasStandardObjects,使用BeanSelectionProvider
这是将配置文件中定义的<bean>与实际的类相映射,就是注入bean的依赖关系,这部分以后有时候再研究Container
 
接下来是看怎样调用这些ConfigurationProviders
展开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;     
 }     
      //再看getConfiguration()     
 public synchronized Configuration getConfiguration() {     
     if (configuration == null) {     
         setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));     
         try {     
//重点就是这个reloadContainer     
             configuration.reloadContainer(getContainerProviders());     
         } catch (ConfigurationException e) {     
             setConfiguration(null);     
             throw new ConfigurationException("Unable to load configuration.", e);     
         }     
     } else {     
         conditionalReload();     
     }     
    
     return configuration;     
 } 
展开DefaultConfiguration中的reloadContainer

public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {     
      packageContexts.clear();     
      loadedFileNames.clear();     
      List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();     
    
//Struts2(xwork2)用Container来完成依赖注入的功能     
//首先初始化一个ContainerBuilder,再由builder来保存接口与实现类或工厂类的对应关系     
//然后通过builder.create(boolean)方法产生container     
//由container.getInstance(Class);就可以得到接口的实现实例了     
//这一部分比较复杂,后面研究完成了,会单独拿出来讲,这里先弄清楚Xwork依赖注入的实现步骤就可以了     
      ContainerProperties props = new ContainerProperties();     
      ContainerBuilder builder = new ContainerBuilder();     
      for (final ContainerProvider containerProvider : providers)     
      {     
    //循环调用ConfigurationProvider的init和register方法,明白了吧,在这里统一循环调用     
          containerProvider.init(this);     
          containerProvider.register(builder, props);     
      }     
      props.setConstants(builder);     
      //注入依赖关系,在这里并不产生实例     
      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     
          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的loadPackages()方法,这里主要是针对XmlConfigurationProvider和StrutsXmlConfigurationProvider     
                  ((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) {     
              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);     
          }     
      }     
      return packageProviders;     
  }     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值