MoudleConfig初始化的实现

这篇博客详细解析了 Apache Struts 中 ModuleConfig 的初始化过程。从 initModuleConfigFactory 方法开始,根据 ServletConfig 中的参数决定使用哪个 ModuleConfigFactory。接着介绍了如何创建并配置 ModuleConfig,包括使用 Digester 处理资源路径,以及初始化各种配置对象如 ActionConfig、FormBeanConfig 等。同时,还展示了如何通过自定义的 ModuleConfigFactory 类 UserModuleConfigFactory 来覆盖默认配置。
摘要由CSDN通过智能技术生成
上回说到Struts的ActionServlet,其中有一步是 initModuleConfig方法,就是用于初始化MoudleConfig实例,它是整个org.apache.struts.config包的核心,在Struts应用运行时用来存放整个Struts应用的配置信息.如果有多个子应用,每个子应用都会有一个ModuleConfig对象.ModuleConfig和Struts配置文件的根元素<struts-config>对应.<struts-config>根元素中包含<form-bean>,<action>和<forward>等一系列子元素,因此MouduleConfig中包含了和每个子元素对应的配置类实例.

同时Struts中的MessageResource、PlugIn、数据源等,都是通过ModuleConfig来实现的,所以在ActionServlet初始化上面的那些模块之前,就先要初始化ModuleConfig,然后由ModuleConfig来负责其初始化。

struts中读取模块配置MoudleConfig采用了这样的工厂方法
一个接口:ModuleConfig.java
一个抽象类:ModuleConfigFactory.java
一个ModuleConfig的实现类:ModuleConfigImpl.java
一个ModuleConfigFactory的子类:DefaultModuleConfigFactory.java

具体介绍
一.initModuleConfigFactory()
在ActionServlet初始化ModuleConfig的时候,先要初始化配置工厂,
Java代码 复制代码
  1. initModuleConfigFactory();  
initModuleConfigFactory();


那么这个工厂到底初始化了什么?
现看源代码:
Java代码 复制代码
  1. protected void initModuleConfigFactory(){   
  2.         String configFactory = getServletConfig().getInitParameter("configFactory");   
  3.         if (configFactory != null) {   
  4.             ModuleConfigFactory.setFactoryClass(configFactory);   
  5.         }   
  6. }  
protected void initModuleConfigFactory(){
        String configFactory = getServletConfig().getInitParameter("configFactory");
        if (configFactory != null) {
            ModuleConfigFactory.setFactoryClass(configFactory);
        }
}

很明显,现从配置参数取得其配置,如果用户没有作配置,那么就使用默认配置,如果用户作了配置,那么就使用用户的配置。
如果用户作了配置的话,那么就执行设置成用户的工厂。如何设置的呢?
Java代码 复制代码
  1. public static void setFactoryClass(String factoryClass) {   
  2.     ModuleConfigFactory.factoryClass = factoryClass;   
  3.     ModuleConfigFactory.clazz = null;   
  4. }  
    public static void setFactoryClass(String factoryClass) {
        ModuleConfigFactory.factoryClass = factoryClass;
        ModuleConfigFactory.clazz = null;
    }

直接给ModuleConfigFactory.factoryClass赋值,因为此变量是一个静态的变量:
   
Java代码 复制代码
  1. protected static String factoryClass =   
  2.         "org.apache.struts.config.impl.DefaultModuleConfigFactory";  
protected static String factoryClass =
        "org.apache.struts.config.impl.DefaultModuleConfigFactory";

由此定义决定了可以使用此赋值方法。正是因为此变量是一个静态的变量,所以在下面的得工厂生成对象的时候就可以创建一个用户自己的对象。

二.initModuleConfig()
之后由配置工厂再实例化一个ModuleConfig的对象。
Java代码 复制代码
  1. ModuleConfig moduleConfig = initModuleConfig("", config);  
ModuleConfig moduleConfig = initModuleConfig("", config);


看一下initModuleConfig方法是如何初始化ModuleConfig的,看下面的源代码:
Java代码 复制代码
  1. protected ModuleConfig initModuleConfig(String prefix, String paths)   
  2.      throws ServletException {   
  3.  //这个地方,我们可以看到,此时就由ModuleConfigFactory直接创建了一个工厂对象,而此时我们用的配置就是上面我们初始化后的配置。如果用户自己做了配置,那么此时初始化的工厂就是用户指定后的工厂。如果没有的话,那么就初始化的时默认的工厂。   
  4. DefaultModuleConfigFactory的一个实例   
  5.         ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();   
  6.      ModuleConfig config = factoryObject.createModuleConfig(prefix);   
  7.      // Configure the Digester instance we will use   
  8.      Digester digester = initConfigDigester();   
  9.   
  10.      // Process each specified resource path   
  11.      while (paths.length() > 0) {   
  12.          digester.push(config);   
  13.          String path = null;   
  14.          int comma = paths.indexOf(',');   
  15.          if (comma >= 0) {   
  16.              path = paths.substring(0, comma).trim();   
  17.              paths = paths.substring(comma + 1);   
  18.          } else {   
  19.              path = paths.trim();   
  20.              paths = "";   
  21.          }   
  22.   
  23.          if (path.length() < 1) {   
  24.              break;   
  25.          }   
  26.   
  27.          this.parseModuleConfigFile(digester, path);   
  28.      }   
  29.   
  30.      getServletContext().setAttribute(   
  31.          Globals.MODULE_KEY + config.getPrefix(),   
  32.          config);   
  33.   
  34.      // Force creation and registration of DynaActionFormClass instances   
  35.      // for all dynamic form beans we wil be using   
  36.      FormBeanConfig fbs[] = config.findFormBeanConfigs();   
  37.      for (int i = 0; i < fbs.length; i++) {   
  38.          if (fbs[i].getDynamic()) {   
  39.              fbs[i].getDynaActionFormClass();   
  40.          }   
  41.      }   
  42.   
  43.      return config;   
  44.  }  
   protected ModuleConfig initModuleConfig(String prefix, String paths)
        throws ServletException {
    //这个地方,我们可以看到,此时就由ModuleConfigFactory直接创建了一个工厂对象,而此时我们用的配置就是上面我们初始化后的配置。如果用户自己做了配置,那么此时初始化的工厂就是用户指定后的工厂。如果没有的话,那么就初始化的时默认的工厂。
也就是DefaultModuleConfigFactory的一个实例
           ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();
        ModuleConfig config = factoryObject.createModuleConfig(prefix);
        // Configure the Digester instance we will use
        Digester digester = initConfigDigester();

        // Process each specified resource path
        while (paths.length() > 0) {
            digester.push(config);
            String path = null;
            int comma = paths.indexOf(',');
            if (comma >= 0) {
                path = paths.substring(0, comma).trim();
                paths = paths.substring(comma + 1);
            } else {
                path = paths.trim();
                paths = "";
            }

            if (path.length() < 1) {
                break;
            }

            this.parseModuleConfigFile(digester, path);
        }

        getServletContext().setAttribute(
            Globals.MODULE_KEY + config.getPrefix(),
            config);

        // Force creation and registration of DynaActionFormClass instances
        // for all dynamic form beans we wil be using
        FormBeanConfig fbs[] = config.findFormBeanConfigs();
        for (int i = 0; i < fbs.length; i++) {
            if (fbs[i].getDynamic()) {
                fbs[i].getDynaActionFormClass();
            }
        }

        return config;
    }


三.createModuleConfig()方法
那么初始化配置模块createModuleConfig方法到底做了什么呢?
其实是生成了一个ModuleConfig的对象。这个对象是由其工厂产生的,由什么样的工厂就会生成什么样的产品。所以如果是用户配置过的工厂,那么就会生成其对应的配置模块的实现。
默认的情况:
Java代码 复制代码
  1. public class DefaultModuleConfigFactory extends ModuleConfigFactory implements Serializable{   
  2.     // --------------------------------------------------------- Public Methods   
  3.   
  4.     /**  
  5.      * Create and return a newly instansiated {@link ModuleConfig}.  
  6.      * This method must be implemented by concrete subclasses.  
  7.      *  
  8.      * @param prefix Module prefix for Configuration  
  9.      */  
  10.     public ModuleConfig createModuleConfig(String prefix) {   
  11.   
  12.         return new ModuleConfigImpl(prefix);   
  13.   
  14.     }   
  15. }  
public class DefaultModuleConfigFactory extends ModuleConfigFactory implements Serializable{
    // --------------------------------------------------------- Public Methods

    /**
     * Create and return a newly instansiated {@link ModuleConfig}.
     * This method must be implemented by concrete subclasses.
     *
     * @param prefix Module prefix for Configuration
     */
    public ModuleConfig createModuleConfig(String prefix) {

        return new ModuleConfigImpl(prefix);

    }
}

它的createModuleConfig(String prefix)方法会生成一个ModuleConfigImpl类。

四.ModuleConfigImpl类
    ModuleConfigImpl类相当于一个JavaBean,用来存放一个web模块运行时所需要的配置信息。当 然,一个web模块可以拥有多个ModuleConfig,但是缺省的是prefix长度为0的ModuleConifg。它 的每个属性几乎都是由HashMap组成的,它通过一个configured布尔值来描述当前的ModuleConfig是否已经被初始化完毕,在每存放一个属性的时候都会监测这个值。如果初始化完毕而还要改变里面的属性值,则会报出IllegalStateException("Configuration is frozen")异常,
现在对它的属性简单说明如下:
     
Java代码 复制代码
  1. // 这个HashMap用来存储ActionConfig对象。   
  2. protected HashMap actionConfigs:   
  3. //HashMap用来存储DataSourceConfig对象。   
  4. protected HashMap dataSources   
  5. //这个HashMap用来存储ExceptionConfig对象。   
  6. protected HashMap exceptions   
  7. //这个HashMap用来存储FormBeanConfig对象。   
  8.  protected HashMap formBeans   
  9. //这个HashMap用来存储ForwardConfig对象。   
  10.  protected HashMap forwards   
  11. //这个HashMap用来存储MessageResourcesConfig对象。   
  12.   protected HashMap messageResources   
  13. //这个HashMap用来存储PlugInConfig对象。   
  14.    protected ArrayList plugIns   
  15. //ControllerConfig类   
  16.   protected ControllerConfig controllerConfig   
  17. //标志这个ModuleConfig是(true)否(false)配置完成。   
  18.     protected boolean configured   
  19. //用来标志和区分ModuleConfig类,同时在使用上面的config类初始化相应的资源以后,也是通过这个prefix来区分所属的不同的web模块。   
  20.   protected String prefix   
  21. //ActionMapping类名,缺省为org.apache.struts.action.ActionMapping。[   
  22.   protected String actionMappingClass = "org.apache.struts.action.ActionMapping"  
// 这个HashMap用来存储ActionConfig对象。
protected HashMap actionConfigs:
//HashMap用来存储DataSourceConfig对象。
protected HashMap dataSources
//这个HashMap用来存储ExceptionConfig对象。
protected HashMap exceptions
//这个HashMap用来存储FormBeanConfig对象。
 protected HashMap formBeans
//这个HashMap用来存储ForwardConfig对象。
 protected HashMap forwards
//这个HashMap用来存储MessageResourcesConfig对象。
  protected HashMap messageResources
//这个HashMap用来存储PlugInConfig对象。
   protected ArrayList plugIns
//ControllerConfig类
  protected ControllerConfig controllerConfig
//标志这个ModuleConfig是(true)否(false)配置完成。
    protected boolean configured
//用来标志和区分ModuleConfig类,同时在使用上面的config类初始化相应的资源以后,也是通过这个prefix来区分所属的不同的web模块。
  protected String prefix
//ActionMapping类名,缺省为org.apache.struts.action.ActionMapping。[
  protected String actionMappingClass = "org.apache.struts.action.ActionMapping"


ModuleConfigImpl类的ModuleConfigImpl方法如下
Java代码 复制代码
  1. public ModuleConfigImpl(String prefix) {   
  2.       super();   
  3.       this.prefix = prefix;   
  4.       this.actionConfigs = new HashMap();   
  5.       this.actionConfigList = new ArrayList();   
  6.       this.actionFormBeanClass = "org.apache.struts.action.ActionFormBean";   
  7.       this.actionMappingClass = "org.apache.struts.action.ActionMapping";   
  8.       this.actionForwardClass = "org.apache.struts.action.ActionForward";   
  9.       this.configured = false;   
  10.       this.controllerConfig = null;   
  11.       this.dataSources = new HashMap();   
  12.       this.exceptions = new HashMap();   
  13.       this.formBeans = new HashMap();   
  14.       this.forwards = new HashMap();   
  15.       this.messageResources = new HashMap();   
  16.       this.plugIns = new ArrayList();   
  17.   }  
  public ModuleConfigImpl(String prefix) {
        super();
        this.prefix = prefix;
        this.actionConfigs = new HashMap();
        this.actionConfigList = new ArrayList();
        this.actionFormBeanClass = "org.apache.struts.action.ActionFormBean";
        this.actionMappingClass = "org.apache.struts.action.ActionMapping";
        this.actionForwardClass = "org.apache.struts.action.ActionForward";
        this.configured = false;
        this.controllerConfig = null;
        this.dataSources = new HashMap();
        this.exceptions = new HashMap();
        this.formBeans = new HashMap();
        this.forwards = new HashMap();
        this.messageResources = new HashMap();
        this.plugIns = new ArrayList();
    }

通过其默认工厂的实现,我们可以看到,其实例化了一个ModuleConfigImpl的对象,这是ModuleConfig的一种实现,也是当前struts的默认的实现。

这是初始化过程开始逐渐明朗.
调用过程factoryObject.createModuleConfig(prefix)--->DefaultModuleConfigFactory 的createModuleConfig(prefix)---->new ModuleConfigImpl(prefix),但好像还有一个问题,ModuleConfigImpl类的ModuleConfigImpl方法里对其属性都是new的,没赋值啊?后来仔细看了半天,发现在initModuleConfig方法里还有几行代码
Java代码 复制代码
  1. .......   
  2.  Digester digester = initConfigDigester();   
  3. .......   
  4. igester.push(config);   
  5.  .......   
  6.  this.parseModuleConfigFile(digester, path);   
  7. .....  
  .......
   Digester digester = initConfigDigester();
  .......
 digester.push(config);
   .......
   this.parseModuleConfigFile(digester, path);
  .....

应该是digster携带config实例在parseModuleConfigFile方法里初始化好了.

五.UserModuleConfigFactory
如果是用户配置了实现工厂的话,可能的实现就是:
Java代码 复制代码
  1. public class UserModuleConfigFactory extends ModuleConfigFactory implements Serializable{   
  2.        public ModuleConfig createModuleConfig(String prefix) {   
  3.         return new ModuleConfigUserImpl(prefix);   
  4.     }   
  5. }  
public class UserModuleConfigFactory extends ModuleConfigFactory implements Serializable{
       public ModuleConfig createModuleConfig(String prefix) {
        return new ModuleConfigUserImpl(prefix);
    }
}

    当然,如果要启用你的工厂的话,那么还要在你的配置文件中添加如下部分,在web.xml中修改如下部分:
Java代码 复制代码
  1. <servlet>   
  2.     <servlet-name>action</servlet-name>   
  3.     <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>   
  4.     <init-param>   
  5.       <param-name>config</param-name>   
  6.       <param-value>/WEB-INF/struts-config.xml</param-value>   
  7.     </init-param>   
  8.     <init-param>   
  9.       <param-name>debug</param-name>   
  10.       <param-value>3</param-value>   
  11.     </init-param>   
  12.     <init-param>   
  13.       <param-name>detail</param-name>   
  14.       <param-value>3</param-value>   
  15. </init-param>   
  16.   
  17.     <init-param>   
  18.       <param-name>configFactory</param-name>   
  19.       <param-value>org.aa.struts. UserModuleConfigFactory </param-value>   
  20. </init-param>   
  21.   
  22.     <load-on-startup>0</load-on-startup>   
  23.   </servlet>  
<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>
      <param-value>3</param-value>
    </init-param>
    <init-param>
      <param-name>detail</param-name>
      <param-value>3</param-value>
</init-param>

    <init-param>
      <param-name>configFactory</param-name>
      <param-value>org.aa.struts. UserModuleConfigFactory </param-value>
</init-param>

    <load-on-startup>0</load-on-startup>
  </servlet>

这样的话,你的工厂就可以生效了,也可以生成你自己的配置模块的实例了。

到此,配置模块MoudelConfig的初始化也已经完成.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值