Tomcat 源码分析-启动分析(3)
文章目录
Catalina对象的load、start方法与Digester解析器
前边说道,Bootstrap的main方法最后调用了 org.apache.catalina.startup.Catalina 的 load 和 start 两个方法 。
总的概括的操作内容:
- 首先,load方法:解析了server.xml文件,并生成了对应的server等对象并初始化。
- 然后,start方法调用了解析初始化出来的server.start方法。【具体类为:StandardServer】
接下来,具体看一下这两个方法的东东吧。。
Catalina.load() 方法分析
load的部分源码 【因为有很多判断的代码,就删减了】
代码主要功能:初始化xml加载器Digester,配置其各种解析规则。然后将类本身入栈,并执行parse解析server.xml文件流,生产各种对应的实例类,并关联到类本身的server。
最后在初始化解析生产的server的init初始化方法。
public void load() { initDirs();//初始化文件目录 initNaming();//初始化命名空间 // Create and execute our Digester : 这个是一个SAX模式解析xml的类。 Digester digester = createStartDigester(); /*server.xml的资源流*/ InputSource inputSource = null; InputStream inputStream = null; File file = null; inputSource.setByteStream(inputStream); //将当前对象压入栈。保存一个到 Digester 生成的一系列对象直接的引用,方便后续使用 digester.push(this); //parse 方法解析 xml,生成相应的对象 digester.parse(inputSource); getServer().setCatalina(this); // Start the new server 这里是就是:StandardServer.init() getServer().init(); }
这里主要就是进行解析xml的了,核心的地方在Digester类的创建,它是进行解析并生成对应的server的处理类。
这里load最后调用的方法是
getServer().init();
【这里就是StandardServer
类】
分析Digester类的操作
这里先来分析一下,代码中提到的Digester类,用来解析加载xml配置文件的,并且创建相应的Server服务的。
下面是
createStartDigester()
方法,主要的功能是:创建和配置Digester解析器。/** * Create and configure the Digester we will be using for startup. */ protected Digester createStartDigester() { long t1=System.currentTimeMillis(); // Initialize the digester Digester digester = new Digester(); // 设置为false表示解析xml时不需要进行DTD的规则校验 digester.setValidating(false); // 是否进行节点设置规则校验,如果xml中相应节点没有设置解析规则会在控制台显示提示信息 digester.setRulesValidation(true); // 将xml节点中的className作为假属性,不必调用默认的setter方法(一般的节点属性在解析时将会以属性值作为入参调用该节点相应对象的setter方法, // 而className属性的作用是提示解析器用该属性的值来实例化对象) Map<Class<?>, List<String>> fakeAttributes = new HashMap<Class<?>, List<String>>(); List<String> objectAttrs = new ArrayList<String>(); objectAttrs.add("className"); fakeAttributes.put(Object.class, objectAttrs); // Ignore attribute added by Eclipse for its internal tracking List<String> contextAttrs = new ArrayList<String>(); contextAttrs.add("source"); fakeAttributes.put(StandardContext.class, contextAttrs); digester.setFakeAttributes(fakeAttributes); digester.setUseContextClassLoader(true); // Configure the actions we will be using // addObjectCreate方法的意思是碰到xml文件中的Server节点则创建一个MyStandardServer对象 digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className"); // 根据Server节点中的属性信息调用相应属性的setter方法,以上面的xml文件为例则会调用setPort、setShutdown方法,入参分别是8005、SHUTDOWN digester.addSetProperties("Server"); // 将Server节点对应的对象作为入参调用栈顶对象的setServer方法,这里的栈顶对象即下面的digester.push方法所设置的当前类的对象this,就是说调用Catalina类的setServer方法 digester.addSetNext("Server", "setServer", "org.apache.catalina.Server"); "org.apache.catalina.deploy.NamingResources"); 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"); 。。。 // Add RuleSets for nested elements 为嵌套元素添加规则集 digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/")); 。。。 return (digester); }
这里一堆操作之后,初始化好digester的解析规则。
其中server的addSetNext规则说明了会调用栈顶对象的setServer方法,就是说调用Catalina类的setServer方法。【会将实例化的org.apache.catalina.core.StandardServer对象返到setServer方法】
Catalina.start() 方法分析
getServer().start();
对,核心代码,就这个一句话。
调用
StandardServer.start();
关于这里的Server
这里所创建的server是org.apache.catalina.Server接口的一个实现类StandardServer。
public final class StandardServer extends LifecycleMBeanBase implements Server {}
这里涉及到了
LifecycleMBeanBase
,Tomcat的容器生命周期( Lifecycle j) (⊙_⊙)?代码中最后的
getServer().start()
和getServer().init()
所指的就是Lifecycle
接口的方法。接下来要了解的就是这一个东东了。
参考
http://www.iocoder.cn/Tomcat/yuliu/Start-analysis-3-Digester/
小杭
邮箱:xiao_hang0_0@163.com