这个方法主要设置(这个方法很重要,贵在理解,虽然还没学过设计模式。。)

1、遇到<server>标签时创建StandardServer实例

   设置StandardServer类内部的相关属性

   并调用Catalina.setServer()方法设置server

2、遇到<Server>标签的子标签<Listener>==》对应匹配模式"Server/Listener"时

  创建Listener实例,创建类名通过<Listener className=要创建的全类名(包名+类名)>获取属性className的值进行创建。

 调用StandardServer的addLifecycleListener()为server添加监听器

3、<Service>标签时即匹配模式为:"Server/Service"创建StandardService实例,放入Stack栈中,调用addSetProperties方法为StandardService设置相关属性

 

digester.addSetNext("Server/Service",
"addService",
"org.apache.catalina.Service");

调用Service的parent=stack.peek(1)即Server对象的addService方法为与Server关联。

4、同2一样为Service设置监听器

5、<executor>标签时即匹配模式:"Server/Service/Executor" 生成StandardThreadExecutor实例,

   设置StandardThreadExecutor的属性

  调用其父类Service的addExecutor方法与Service关联

6、调用addRule方法如上一样,

pattern:"Server/Service/Connector"==>创建Connector实例,设置属性,调用StandardService.addConnector()。为Connector设置监听器

7、调用addRuleSet()方法

digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));

跟6一样

、、设置Engine

EngineRuleSet(String prefix)当遇到模式为prefix + "Engine"即"Server/Service/Engine"会在EngineRuleSet.addRuleInstances()内部调用

addObjectCreate、addSetProperties、addRule这三个方法创建StandardEngine实例,设置属性,调用Service。setContainer()方法。

创建SimpleTcpCluster实例调用Engine.setCluster()方法

给Engine添加监听器,

创建realm对象实例,调用对应方法与Engine关联。

创建AccessLogValve日志对象(将日志输出到。txt文件),设置属性,与engine关联。

、、设置host

创建StandardHost,设置属性,设置监听器:HostConfig

调用Container。addChild()在这里Container即与Engine相关联

、、设置context

创建StandardContext,设置属性,设置监听器:ContextConfig

调用Container。addChild()在这里Container即与Host相关联

创建WebappLoader,与StandardContext关联

创建StandardManager,与StandardContext关联

创建store存储类,与StandardContext关联

创建StandardSessionIdGenerator,与StandardManager关联

创建ApplicationParameter,与StandardContext关联

创建realm对象实例,与StandardContext关联

创建StandardRoot,与StandardContext关联

  context==》WebResourceRoot==StandardRoot设置

  org.apache.catalina.webresources.StandardRoot提供各种resources实现类

  创建WebResourceSet,与StandardRoot关联

  (WebResourceSet的实现类有WarResourceSet、JarResourceSet、JarWarResourceSet、DirResourceSet、FileResourceSet等)

  主要设置StandardRoot的preResources、jarResources、postResources这三个变量的实例

创建ContextResourceLink,与StandardContext关联

创建AccessLogValve,与StandardContext关联

创建StandardJarScanner,与StandardContext关联

  创建StandardJarScanFilter,与StandardJarScanner关联

创建LegacyCookieProcessor与StandardContext关联

Note:上面已经说明完的具体对象被创建的整个过程,下面是对Digester的一些方法的理解。可以忽略!


protected Digester createStartDigester() {
long t1=System.currentTimeMillis();
// Initialize the digester
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
ArrayList<String> attrs = new ArrayList<>();
attrs.add("className");
fakeAttributes.put(Object.class, attrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true); // Configure the actions we will be using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server"); digester.addObjectCreate("Server/GlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources",
"setGlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl"); digester.addObjectCreate("Server/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Listener");
digester.addSetNext("Server/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener"); digester.addObjectCreate("Server/Service",
"org.apache.catalina.core.StandardService",
"className");
digester.addSetProperties("Server/Service");
digester.addSetNext("Server/Service",
"addService",
"org.apache.catalina.Service"); digester.addObjectCreate("Server/Service/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener"); //Executor
digester.addObjectCreate("Server/Service/Executor",
"org.apache.catalina.core.StandardThreadExecutor",
"className");
digester.addSetProperties("Server/Service/Executor"); digester.addSetNext("Server/Service/Executor",
"addExecutor",
"org.apache.catalina.Executor"); digester.addRule("Server/Service/Connector",
new ConnectorCreateRule());
digester.addRule("Server/Service/Connector",
new SetAllPropertiesRule(new String[]{"executor"}));
digester.addSetNext("Server/Service/Connector",
"addConnector",
"org.apache.catalina.connector.Connector"); digester.addObjectCreate("Server/Service/Connector/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener"); // Add RuleSets for nested elements
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/")); // When the 'engine' is found, set the parentClassLoader.
digester.addRule("Server/Service/Engine",
new SetParentClassLoaderRule(parentClassLoader));
addClusterRuleSet(digester, "Server/Service/Engine/Cluster/"); long t2=System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("Digester for server.xml created " + ( t2-t1 ));
}
return (digester); }

addObjectCreate()//Add an "object create" rule for the specified parameters.增加对象创建规则.遇到起始标签的元素,初始化一个实例对象入栈

addSetProperties()//Add a "set properties" rule for the specified parameters.增加设置属性规则.遇到某个属性名,使用setter来赋值

digester.addSetProperties("Server");

对应标签<Server port="8005" shutdown="SHUTDOWN">

遇到匹配模式为:Server。addSetProperties方法会反射调用StandardServer对象的setPort(int) 和setShutdown(String)两个方法设置属性

 
Digester.addSetNext(String pattern, String methodName, String paramType)

//Add a "set next" rule for the specified parameters.增加set next规则.遇到下一标签时的动作

即反射调用方法名为methodName的方法。

digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
当遇到<Server>标签的下一标签时被调用

addSetNext方法会调用SetNextRule.end()方法会调用这个当前top栈顶对象的parent父对象(栈顶对象的下一个元素)的setServer()方法

当StandardServer对象入栈后,栈中已经存在Catalina对象===>在Catalina.load()方法中设置了

所以StandardServer的parent父对象是Catalina,即调用Catalina.setServer()方法设置server属性。

addRule:调用rule的begin 、body、end、finish方法来解析xml,入栈和出栈给对象赋值

addRuleSet:调用addRuleInstances来解析xml标签


addObjectCreate(pattern ,className ,attributeName

1、

Add an "object create" rule for the specified parameters为指定的参数增加一个对象创建规则.

Parameters:
pattern Element matching pattern元素匹配模式
className Default Java class name to be created要创建的java类的名字
attributeName Attribute name that optionally overrides the default Java class name to be created属性名称可以覆盖要创建的默认Java类名称
获取xml文件中attributes属性名为:className所对应的值替换第二个参数
ObjectCreateRule.java类的begin(String namespace, String name, Attributes attributes)方法,
这个方法将通过类名加载Class然后调用class.newInstance()生成类实例,最后放入digest的对象栈顶digester.push(instance);
String realClassName = className;
if (attributeName != null) {
String value = attributes.getValue(attributeName);
if (value != null) {
realClassName = value;
}
}
Digester.addObjectCreate(String pattern, String className, String attributeName)

这个addObjectCreate()方法又调用addRule()方法

2、

Register a new Rule matching the specified pattern. This method sets the Digester property on the rule.

Parameters:
pattern Element matching pattern
rule Rule to be registered这里的rule使用的是ObjectCreateRule
Digester.addRule(String pattern, Rule rule)
addRule(pattern, new ObjectCreateRule(className, attributeName));
public void addRule(String pattern, Rule rule) {

        rule.setDigester(this);设置digester,将保存创建的对象的实例
getRules().add(pattern, rule);这里将会返回Rules接口的实现类。然后再调用Rules.add()来添加Rule实例 }
Note:Rules:是一个接口public interface Rules
        公共接口定义规则实例的集合(和相应的匹配模式)以及匹配策略的实现,
        该策略选择与解析期间发现的嵌套元素的特定模式匹配的规则。
   Rule:是一个抽象类public abstract class Rule

ObjectCreateRule类的解释

Rule implementation that creates a new object and pushes it onto the object stack. When the element is complete, the object will be popped

Rule实现类,创建一个新对象并将其推送到对象堆栈上。当元素完成时,对象将被弹出

3、RuleBase.add(pattern, rule)

public void add(String pattern, Rule rule) {
// to help users who accidently add '/' to the end of their patterns
int patternLength = pattern.length();
if (patternLength>1 && pattern.endsWith("/")) {
pattern = pattern.substring(0, patternLength-1);
} List<Rule> list = cache.get(pattern);
if (list == null) {
list = new ArrayList<>();
cache.put(pattern, list);
}
list.add(rule);
rules.add(rule);
if (this.digester != null) {
rule.setDigester(this.digester);
}
if (this.namespaceURI != null) {
rule.setNamespaceURI(this.namespaceURI);
} }

上面方法用用HashMap<String, List<Rule>>类型变量cache存放pattern和Rule集合,用rules集合存放新加入的规则rules.add(rule)

Digester.addSetProperties(String pattern)
这个方法跟addObjectCreate方法调用相似顺序如下
1addRule(pattern, new SetPropertiesRule());
2getRules().add(pattern, rule);
3RulesBase.add(pattern, rule)
Digester.addSetNext(String pattern, String methodName, String paramType)
1addRule(pattern, new SetNextRule(methodName, paramType));
2getRules().add(pattern, rule);
3RulesBase.add(pattern, rule)

注:

只有当遇到改元素的结束标签时才会将改标签代表的对象实例弹出栈。

Catalina.createDigester方法详细理解的更多相关文章

  1. iOS - 详细理解KVC与KVO

    详细理解KVC与KVO 在面试的时候,KVC与KVO有些时候还是会问到的,并且他们都是Objective C的关键概念,在这里我们先做一个简单地介绍: (一)KVC: KVC即指:NSKeyValue ...

  2. S5中新增的Array方法详细说明

      ES5中新增的Array方法详细说明 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wor ...

  3. win8.1系统的安装方法详细图解教程

    win8.1系统的安装方法详细图解教程 关于win8.1系统的安装其实很简单 但是有的童鞋还不回 所以今天就抽空做了个详细的图解教程, 安装win8.1系统最好用U盘安装,这样最方便简单 而且系统安装 ...

  4. 转载:JAVA中关于set()和get()方法的理解及使用

    对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...

  5. [转]Android View.onMeasure方法的理解

    转自:http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html Android View.onMeasure方法的理解 View在屏幕上显示出来要先经过 ...

  6. ASP.NET MVC3 局部页面@RENDERBODY @RENDERPAGE@RENDERSECTION使用方法详细说明

    转载自:http://blog.163.com/wenchangqing_live/blog/static/173722309201211299817278/ asp.net mvc3局部页面使用方法 ...

  7. 五种I/O 模式,select、epoll方法的理解,BIO、NIO、AIO理解 相关文章

    一.io方式 Linux网络编程 五种I/O 模式及select.epoll方法的理解 web优化必须了解的原理之I/o的五种模型和web的三种工作模式 五种I/O 模式——阻塞(默认IO模式),非阻 ...

  8. initWithFrame方法的理解

    initWithFrame方法的理解   有时候,知道initWithFrame方法如何用,但是么有弄明白initWithFrame方法到底是什么? 那就通过查资料弄明白.     1. initWi ...

  9. java中set和get方法的理解

    对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...

随机推荐

  1. C++总的const使用说明

    C++总的const使用说明 1. const修饰类成员变量 程序: #include <iostream> using namespace std; class A { public: ...

  2. 自定义cscope-index

    目标: 1)生成索引文件时可以包含java文件: 2)cscope.in.out和cscope.po.out文件,加快cscope的索引速度 3)生成索引文件时,不搜索/usr/include目录 解 ...

  3. Python学习-1.安装Python

    到Python的官方网站 https://www.python.org/downloads/ 下载官方的安装包 https://www.python.org/ftp/python/3.4.1/pyth ...

  4. C# 二维码/条形码入门操作

    效果图: 先给之前的群友道个歉,说声不好意思.QRCoder 只支持二维码,没有条形码. 以上demo生成条形码是用 BarcodeLib 这个库,识别是用 zxing,二维码生成用 QRCoder, ...

  5. MongoDB的下载、安装与部署方法

    1.什么是MongoDB? 它是介于关系型数据库和非关系型数据库之间的一种NoSQL数据库,用C++编写,是一款集敏捷性.可伸缩性.扩展性于一身的高性能的面向文档的通用数据库. 2.为什么要用Mong ...

  6. EF学习笔记-1 EF增删改查

    首次接触Entity FrameWork,就感觉非常棒.它节省了我们以前写SQL语句的过程,同时也让我们更加的理解面向对象的编程思想.最近学习了EF的增删改查的过程,下面给大家分享使用EF对增删改查时 ...

  7. web安全之——XSS、CSRF

    XSS漏洞 XSS 全称 Cross Site Scripting ,跨站脚本攻击.它的形成主要原因是多数用户输入没有转义,而被直接执行. 参考下面一段脚本: $('#box').html(locat ...

  8. D03——C语言基础学习PYTHON

    C语言基础学习PYTHON——基础学习D03 20180804内容纲要: 1 函数的基本概念 2 函数的参数 3 函数的全局变量与局部变量 4 函数的返回值 5 递归函数 6 高阶函数 7 匿名函数 ...

  9. 实验三:分别用for、while和do-while循环语句以及递归方法计算n!,并输出算式

    一.用for循环计算n! package for_package; import java.util.*;//导入含有输入类的包 public class for_class { /** * @par ...

  10. 【xsy1201】 随机游走 高斯消元

    题目大意:你有一个$n*m$的网格(有边界),你从$(1,1)$开始随机游走,求走到$(n,m)$的期望步数. 数据范围:$n≤10$,$m≤1000$. 我们令 $f[i][j]$表示从$(1,1) ...