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);

[img]http://dl.iteye.com/upload/attachment/0080/4616/c467d51e-619e-3309-ab99-54dce116dad5.jpg[/img]

然后在内部利用反射,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文件的结构也类似如此,所以此处选用这种方法,以灵活的方式初始化整个环境,值得学习。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值