• Struts2源码分析 初步2Dispatcher初始化细节(1)


    Struts2 源码初步学习—Dispatcher初始化细节

    先贴代码

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    /**

     * Load configurations, including both XML and zero-configuration strategies,

     * and update optional settings, including whether to reload configurations and resource files.

     */

    publicvoidinit() {

     

        if(configurationManager == null) {

            configurationManager = newConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);

        }

     

        try{

            init_DefaultProperties(); // [1]

            init_TraditionalXmlConfigurations(); // [2]

            init_LegacyStrutsProperties(); // [3]

            init_CustomConfigurationProviders(); // [5]

            init_FilterInitParameters() ; // [6]

            init_AliasStandardObjects() ; // [7]

     

            Container container = init_PreloadConfiguration();

            container.inject(this);

            init_CheckConfigurationReloading(container);

            init_CheckWebLogicWorkaround(container);

     

            if(!dispatcherListeners.isEmpty()) {

                for(DispatcherListener l : dispatcherListeners) {

                    l.dispatcherInitialized(this);

                }

            }

        } catch(Exception ex) {

            if(LOG.isErrorEnabled())

                LOG.error("Dispatcher initialization failed", ex);

            thrownewStrutsException(ex);

        }

    }

    这些小的初始化方法

    都会用到ConfigurationManager这个类的对象。这个类是xwork的配置管理类。

    这个类中涉及两个基础知识ReentrantLock CopyOnWriteArrayList类,详细说明参见JDK

    并注意ReentrantLock基本用法 参见方法 public List<ContainerProvider> getContainerProviders()

    在方法一开始出lock上,在方法的最后finally部分unlock

    看下方法体

    providerLock.lock();

    try {

    if (containerProviders.size() == 0) {

    containerProviders.add(new XWorkConfigurationProvider());

    containerProviders.add(new XmlConfigurationProvider("xwork.xml", false));

    }

     

    returncontainerProviders;

    } finally {

    providerLock.unlock();

    }

    同时这个类中会主要涉及ContainerProvider这个类

    上面是ContainerProvider接口的实现结构

    可以看出struts(xwork)几乎未每种配置做了provider

    看下这个接口定义的方法如下:

    这个接口主要要实现register方法,其中有个参数是ContainerBuilder,这个接口是ContainerProvider,都跟Container有关,别着急,我后面会专门写一篇介绍struts容器的。当然我们在这边关心的不是其register方法,而是init方法,毕竟这篇文章是分析的Dispatcherinit细节

    这个ConfigurationManager有个addContainerProvider方法,主要是用来维护属性

    private List<ContainerProvider> containerProviders = new CopyOnWriteArrayList<ContainerProvider>();

    每当调用一个不同的init方法时,便会用几乎不同的ContainerProviderso这个属性就是用来持有这些provider的列表

     

    不难发现对于类Dispatcher来说是在init方法一开始处初始化

    if (configurationManager == null) {

    configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);

    }

    下面逐一分析那几个init方法

    init_DefaultProperties 方法很简单 就是把DefaultPropertiesProvider加进上面所说的类ConfigurationManagercontainerProviders (是个列表)属性,当然从上面的图不难发现DefaultPropertiesProvider实现了ContainerProvider接口

    init_TraditionalXmlConfigurations这个方法也简单,

    先是从初始化参数中读取有没有配置config这个参数,若没有,default配置文件则用默认的privatestaticfinal String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";

    然后根据这些文件名字的不同做一些特殊处理

    xwork.xml的用XmlConfigurationProvider

    其他的用StrutsXmlConfigurationProvide

    当然仍然是将这些provider加进上面所说的类ConfigurationManagercontainerProviders (是个列表)属性。只是这两个provider的构造方法做了点事情。上面的DefaultPropertiesProvider的构造方法根本没有显式声明

    看下StrutsXmlConfigurationProvide的构造方法做了啥?

    贴下代码一目明了

    super(filename, errorIfMissing);

    this.servletContext = ctx;

    this.filename = filename;

    reloadKey = "configurationReload-"+filename;

    Map<String,String> dtdMappings = new HashMap<String,String>(getDtdMappings());

    dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.0//EN", "struts-2.0.dtd");

    dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.1//EN", "struts-2.1.dtd");

    dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN", "struts-2.1.7.dtd");

    setDtdMappings(dtdMappings);

    File file = new File(filename);

    if (file.getParent() != null) {

    this.baseDir = file.getParentFile();

    }

    setDtdMappings 是为后面解析这些配置文件做校验用的。

    1. init_LegacyStrutsProperties 这个个初始化也没做什么事 对应的providerLegacyPropertiesConfigurationProvider

    1. init_CustomConfigurationProviders 初始化init参数中自定义的(如果有)ConfigurationProvider

    1. init_FilterInitParameters 这个初始化方法中ConfigurationManagercontainerProviders列表中加入一个内部类 new ConfigurationProvider() {…} 这个providerinit方法没做什么事 register方法倒是做了点事情

    2. init_AliasStandardObjects beanSelectionProvider 放进了ConfigurationManagercontainerProviders列表中

    3. init_PreloadConfiguration 初始化容器 这个方法很关键。做了很多事情。包括加载配置文件 包括初始化容器 here --> reloadContainer-->createBootStrap等等。F3跟进去看下,看不出来啥。还要再跟一层,主要是Configuration config = configurationManager.getConfiguration();

      configurationManager类的getConfiguration()方法

      configuration.reloadContainer(getContainerProviders());

      分析 reloadContainer方法,传进来的参数就是上面几步初始化一直在维护的containerProviders(provider列表)

      reloadContainer方法迭代这个provider列表做了两件事情 就是调用每个providerinitregister方法,其实在ContainerProvider接口中能看到定义了这样的方法

      containerProvider.init(this);

      containerProvider.register(builder, props); 这个register方法牵扯到的两个参数,ContainerBuilderContainerProperties两个类的对象,这两个类的对象都是在这个方法体中直接new出来的。

      ContainerProperties props = new ContainerProperties();

      ContainerBuilder builder = new ContainerBuilder();

      ContainerBuilder 的构造方法中将默认两种必要的工厂加到builder的属性final Map<Key<?>, InternalFactory<?>> factories 中。这两中必要的工厂分别是日志工厂和容器工厂。

      这边涉及到接口 InternalFactory 注释为 “ 创建那些将被注入的对象” 。只定义了一个方法

      T create(InternalContext context); 就是创建工厂中的产品。

      这个下面牵扯到的类就相对多点 写法相对绕点了

      <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name,

      InternalFactory<? extends T> factory) {

      return factory;

    未完待续

  • 相关阅读:
    安装Nginx报错:make: *** 没有规则可以创建“default”需要的目标“build”。 停止 安装nginx要先安装那四个依赖 yum y install gcc gccc++ autoconf automake make
    left join的用法
    centos7安装nginx详细步骤 useradd abc 新建用户 在 homg下出现abc文件夹
    虚拟机无法ping通主机,主要是由于公用网络未启用,启用步骤如下:控制面板>系统和安全>Windows Defender 防火墙>页面左侧高级设置>入站规则>下图所示均启用。
    针对idea2020版本,在maven项目中运行程序的时候会出现java程序包不存在现象。 Java程序包不存在问题的解决办法
    main方法运行不起来,报错:xxx.xxx包不存在,xxx.xxx找不到 delegate IDE build/run actions actions to Maven 会默认编译所有模块
    linux 查看nginx 安装路径
    centos7关闭防火墙
    软件汉化:关于.net软件汉化流程说明
    读书札记:QAI关于需求的培训
  • 原文地址:https://www.cnblogs.com/simoncook/p/2266935.html
Copyright © 2020-2023  润新知