`

MoudleConfig初始化的实现

阅读更多
上回说到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的初始化也已经完成.
分享到:
评论

相关推荐

    SIN初始化_混沌初始化_matlab_混沌映射_种群初始化_sin映射初始化粒子群_

    通过混沌映射初始化的粒子群,可以期望在搜索空间中实现更有效的探索,尤其是在解决多模态优化问题时,混沌映射的特性可以帮助粒子避开局部极小值,从而提高全局收敛性能。然而,需要注意的是,混沌映射的参数选择...

    SpringBoot项目启动时实现调用一次初始化方法.docx

    这里我们将详细探讨如何实现这个需求,主要涉及`@PostConstruct`注解、`CommandLineRunner`接口以及在启动类中直接定义初始化方法。 1. **`@PostConstruct`注解** `@PostConstruct`是Java EE规范的一部分,它用于...

    PCI设备BAR空间的初始化

    3. **资源分配的必要条件**:通过初始化BAR寄存器,系统软件可以为每个PCI设备分配特定的地址空间,这是实现资源共享和避免地址冲突的重要步骤。 #### 三、初始化过程详解 ##### 3.1 存储器地址与PCI总线地址的...

    详解Spring 中如何控制2个bean中的初始化顺序

    本篇文章将详细介绍如何控制 2 个 bean 的初始化顺序,提供了多种实现方式,并分析了每种方式的优缺。 问题场景 在实际开发中,我们经常会遇到这样一个场景:2 个 bean 的初始化逻辑中有依赖关系,需要控制二者的...

    C++构造函数初始化列表

    ### C++构造函数初始化列表详解 在C++编程语言中,构造函数是对象生命周期开始时自动调用的特殊成员函数,用于初始化对象的状态。构造函数初始化列表是C++中一个非常重要的特性,它允许程序员在对象创建时直接对类...

    LS-DYNA3D中的应力初始化_lsdyna_应力初始化_

    标题中的“应力初始化”是指在进行LS-DYNA3D模拟时,如何设定初始条件中的应力状态。在进行复杂的工程问题模拟时,正确设置初始应力对于获取准确的计算结果至关重要。 应力初始化通常涉及到以下几个关键知识点: 1...

    比赛工程2,初始化上行至10层;电梯PLC;好像是六部十层;;

    比赛工程2,初始化上行至10层;电梯PLC;好像是六部十层;;比赛工程2,初始化上行至10层;电梯PLC;好像是六部十层;;比赛工程2,初始化上行至10层;电梯PLC;好像是六部十层;;比赛工程2,初始化上行至10层;电梯PLC...

    Revit+外部工具+无法初始化附加模块“CollaborateDB”,因为程序集C:\Prog+无法初始化附加模块的解决方法

    Revit外部工具无法初始化附加模块的解决方法 大家在安装完Revit或者卸载后重装Revit时是否遇到外部工具无法初始化附加模块的问题,每次打开不停的弹出对话框,烦得要死。 无法初始化附加模块“CollaborateDB”,...

    CSS样式初始化commonInitialize.css

    CSS样式初始化是开发过程中一个重要的步骤,它旨在消除浏览器之间的默认样式差异,确保网页在不同浏览器上的一致性表现。"commonInitialize.css"就是这样一个专门用于全局CSS样式初始化的文件。 首先,我们来理解...

    DDR 初始化 流程

    ### DDR初始化流程详解 DDR(Double Data Rate)内存技术在现代计算系统中扮演着至关重要的角色,其高速数据传输能力和高带宽特性使得DDR成为服务器、个人计算机以及各种电子设备中的首选内存类型。DDR初始化流程是...

    类继承的初始化顺序类,继承的初始化顺序

    本文详细介绍了类继承中的初始化顺序问题,包括初始化的基本概念、初始化过程中的关键步骤以及如何正确处理基类和子类之间的构造函数调用。理解这些概念对于编写高效、可维护的面向对象程序至关重要。希望通过对这些...

    typedef struct 与 struct 的区别及初始化

    在C/C++编程语言中,`typedef` 和 `struct` 是两种不同的声明结构体类型...而结构体初始化则涉及到成员变量的初始赋值,可以使用初始化列表来实现。在实际编程中,合理使用 `typedef` 可以提高代码的可读性和可维护性。

    ARM初始化文件详解

    本文将深入探讨ARM初始化文件的结构、功能以及在实际应用中的实现。 一、初始化文件的作用 1. 设置处理器状态:初始化文件首先会设置ARM处理器的工作模式,如复位模式、Thumb模式或ARM模式,以及相应的寄存器初始值...

    各种TFT液晶初始化例程

    初始化过程需设定显示模式、颜色空间、时序参数等,以实现清晰、流畅的图像显示。 在进行TFT液晶屏的初始化编程时,通常会有一个固定的初始化序列,这序列包含了发送一系列特定的命令和参数到液晶屏的控制器。...

    java代码的初始化顺序demo

    `init`文件可能包含了各种构造函数的实现,展示它们如何被调用以及与初始化块交互的方式。 5. **成员变量初始化**: Java允许我们在变量声明时进行初始化。这种初始化发生在构造函数之前,因此在实例初始化块之前...

    ST7701S_IPS.zip

    ST7701是一款专为LCD显示模块设计的驱动芯片,广泛应用在小尺寸彩色液晶屏上,如手机、平板电脑、电子设备的显示...在开发过程中,根据datasheet进行硬件设计,然后编写和调试初始化代码,是实现ST7701驱动的核心步骤。

    解决数码视讯Q5使用USB_Burning_Tool刷机时 提示 初始化DDR/读取初始化结果/USB错误

    解决数码视讯Q5使用USB_Burning_Tool刷机时 提示 初始化DDR/读取初始化结果/USB错误

    ic卡m1卡初始化工具32位

    3. **ICCard.dll**:这是另一个与IC卡操作相关的DLL文件,可能包含了处理IC卡数据读取、写入以及初始化的具体实现。 4. **ICCardInit.exe**:这是一个可执行文件,很可能是主应用程序,用户通过这个程序来运行IC卡...

    ICM20602数据读取及初始化配置

    在实际应用中,ICM20602的数据读取和初始化配置通常通过微控制器的固件实现。例如,在无人机控制系统中,需要定期读取ICM20602的加速度和角速度数据,结合卡尔曼滤波或其他算法进行姿态解算,以实现精准的飞行控制。...

    Nacos 2.1.2 数据库初始化脚本

    Nacos 2.1.2 数据库初始化脚本

Global site tag (gtag.js) - Google Analytics