首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

tomcat7 源码学习札记 2

2013-02-24 
tomcat7 源码学习笔记 2在tomcat中Catalina类启动后,读取sever.xml初始化整个环境,此处使用了一个核心的工

tomcat7 源码学习笔记 2
在tomcat中Catalina类启动后,读取sever.xml初始化整个环境,此处使用了一个核心的工具类,搞定了这些,这个类是:Digester,此类继承自 jdk的DefaultHandler;

我们可以从一个简单的例子来窥视,此处使用server.xml的初始化原理,

Digester规则的设定是这样进行的,选取一组简单的代码如下:

digester.addObjectCreate("Server",                                 "org.apache.catalina.core.StandardServer",                                 "className");        digester.addSetProperties("Server");        digester.addSetNext("Server",                            "setServer",                            "org.apache.catalina.Server");

第一行addObjectCreate的详细内容是这样的:

public void addObjectCreate(String pattern, String className,                                String attributeName) {        addRule(pattern,                new ObjectCreateRule(className, attributeName));    }

内部ObjectCreateRule 实现了Rule接口的两个方法:
public void begin(String namespace, String name, Attributes attributes)            throws Exception {        // Identify the name of the class to instantiate        String realClassName = className;        if (attributeName != null) {            String value = attributes.getValue(attributeName);            if (value != null) {                realClassName = value;            }        }        if (digester.log.isDebugEnabled()) {            digester.log.debug("[ObjectCreateRule]{" + digester.match +                    "}New " + realClassName);        }        if (realClassName == null) {            throw new NullPointerException("No class name specified for " +                    namespace + " " + name);        }        // Instantiate the new object and push it on the context stack        Class<?> clazz = digester.getClassLoader().loadClass(realClassName);        Object instance = clazz.newInstance();        digester.push(instance);    } public void end(String namespace, String name) throws Exception {        Object top = digester.pop();        if (digester.log.isDebugEnabled()) {            digester.log.debug("[ObjectCreateRule]{" + digester.match +                    "} Pop " + top.getClass().getName());        }    }


所以在解析server.xml文件时,如果遇到Server标签,就会触发public void begin(String namespace, String name, Attributes attributes);



然后在内部利用反射,org.apache.catalina.core.StandardServer进行实例化。
如图:

第二行的:        digester.addSetProperties("Server");
也是注册了相应的规则:
public void addSetProperties(String pattern) {        addRule(pattern,                new SetPropertiesRule());    }

在SetPropertiesRule中实现了  public void begin(String namespace, String theName, Attributes attributes)方法。
在其中有 

for (int i = 0; i < attributes.getLength(); i++) {            String name = attributes.getLocalName(i);            if ("".equals(name)) {                name = attributes.getQName(i);            }            String value = attributes.getValue(i);            .....


然后重要的在这里:
if (!digester.isFakeAttribute(top, name)                     && !IntrospectionUtils.setProperty(top, name, value)                     && digester.getRulesValidation()) 

其中:
IntrospectionUtils.setProperty(top, name, value) 


完成了对top对象中name属性设置值为value的动作,这样在server.xml中读取的对应标签的属

性就这样设置到对应的对象中。
第三行: 
digester.addSetNext("Server",                            "setServer",                            "org.apache.catalina.Server");

这种规则是这样设置的:
 public void addSetNext(String pattern, String methodName,                           String paramType) {        addRule(pattern,                new SetNextRule(methodName, paramType));    }

再看如下:
public void end(String namespace, String name) throws Exception {        // Identify the objects to be used        Object child = digester.peek(0);        Object parent = digester.peek(1);        if (digester.log.isDebugEnabled()) {            if (parent == null) {                digester.log.debug("[SetNextRule]{" + digester.match +                        "} Call [NULL PARENT]." +                        methodName + "(" + child + ")");            } else {                digester.log.debug("[SetNextRule]{" + digester.match +                        "} Call " + parent.getClass().getName() + "." +                        methodName + "(" + child + ")");            }        }        // Call the specified method        IntrospectionUtils.callMethod1(parent, methodName,                child, paramType, digester.getClassLoader());                    }

在SetNextRule中只实现了end方法,所以在触发此方法时,调用parent方法中的methodName,设置值为child;
tomcat中的Catalina-->Server->Service->Connector这样的树状结构,正好xml文件的结构也类似如此,所以此处选用这种方法,以灵活的方式初始化整个环境,值得学习。

热点排行