|
引言
上一篇博客我们将源码在本地成功运行了,所以在本篇博客中我们从源码层面分析,在启动的过程中,是如何初始化容器的。我们平常都是将我们的服务部署到中,然后修改一下配置文件,启动就可以对外提供服务了,但是我们对于其中的一些流程并不是非常的了解,例如如何加载的web.xml等。这是我们分析和必不可少的过程。
注释源码地址:
一、代码启动
平常我们不论是还是linux,我们都是通过脚本来启动,这对于我们分析源码不是很友好,所以我们需要通过代码启动,启动代码如下:
1
2
3
4
5
6
7
=new();
.(8080);
//new出各层容器,并且维护各层容器的关系
.("/","/");
.start();
//阻塞监听端口
.().await();
启动代码还是非常非常简单,从代码中我们就可以看出,我们本篇博客主要分析的就是()方法和start()方法,通过这两个方法我们就可以找到容器是在什么时候被初始化的。
二、框架
在我们进行分析上面两个方法之前,我们先总结一下的基础框架,其实从我们非常熟悉的.xml配置文件中就可以知道,就是一系列父子容器组成:
--->-->--->(容器),这就是我们从配置文件中分析出来的几个容器,启动时候就是逐层启动容器。
三、创建容器(())
3.1方法调用流程图
上面的流程图就是,从源码中逐步分析出来的几个重要的方法,这对于我们分析源码非常有帮助。
3.2源码分析
1)通过反射获得监听器
方法路径:org.....(Hosthost,,);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(Hosthost,,){
//通过反射获得一个监听器,
//通过反射得到的一定是的一个实现类,进入得到实现类(org....)
=null;
try{
Classclazz=Class.(().());
=()clazz.().();
}catch(e){
//WrapinIAEsincewecan'ttheto
//tothrowthe
thrownewtion(e);
}
(host,,,);
}
2)获得一个容器()
在下面代码中,()方法通过反射加载容器,并且将设置监听,ctx.();
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
(Hosthost,,,
){
(host,);
//获得一个容器()
ctx=(host,);
ctx.();
ctx.();
if(bapp){
ctx.(ener());
}
ctx.((,));
//把监听器添加到中去
ctx.();
if(bapp&&()){
//itfrom(ifitfindsone-it'llhaveduperror)
(()).(());
}
if(host==null){
//会逐层创建容器,并维护容器父子关系
().(ctx);
}else{
host.(ctx);
}
ctx;
}
3)维护各层容器
()方法中得到各层容器,并且维护父亲容器关系,其中包括,容器、容器。并且将容器通过().(ctx);调用中的()方法维护在这个map中。
1
2
3
4
5
6
7
8
9
10
11
12
13
Host(){
//将每一层的容器都new出来
=();
if(.().>0){
(Host).()[0];
}
Hosthost=new();
host.();
//维护中的父子容器
().(host);
host;
}
().(host);方法选择调用父类中的方法
1
2
3
4
5
6
7
8
9
10
11
@
void(child){
if(.){
dp=
new(child);
.(dp);
}else{
//这里的child参数是容器
(child);
}
}
()方法的核心代码
1
2
3
4
5
6
7
8
9
10
11
12
void(child){
if(log.())
log.debug("Addchild"+child+""+this);
(){
if(.get(child.())!=null)
thrownewtion(":Childname'"+
child.()+
"'isnot");
child.(this);//MaythrowIAE
.put(child.(),child);
}
四、启动容器(.start())
4.1、方法调用流程图
4.2、源码分析
说明:、、等容器都是继承
所以这里是模板模式的经典应用
1)逐层启动容器
此时的对应的是我们前面创建的
1
2
3
4
5
6
7
8
9
voidstart(){
//防止容器没有创建
();
//获得容器,并且将得到的容器设置到容器中
();
//这里的start的实现是在类中实现
//方法是一个模板方法,在启动流程中非常关键
.start();
}
2)进入start方法
进入中的start方法,其中核心方法是。
从上面我们知道现在我们调用的是容器的()方法,所以我们这里选择的是
方法路径:org...core..()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void(){
(T,null);
(.);
s.start();
//Startour
(){
//启动容器,一个中可以配置多个容器,每个容器都对应这我们的一个服务应用
for(:){
//对应.()
.start();
}
}
}
从上面代码中我们可以看出,启动容器的时候需要启动子容器容器天外神坛源码网,从这里开始就是容器逐层向向内引爆,所以接下来就是开始依次调用各层容器的star方法。在这里就不在赘述。
2)中的()方法核心代码,从这开始启动容器
1
2
3
4
5
6
7
8
9
//Startourchild,ifany
//在的流程中方法中加入的,所以这里需要找出来
//这里找出来的就是容器
[]=();
List>=new();
for(child:){
//通过线程池异步的方式启动线程池开始启动容器,进入new
.add(.(new(child)));
}
new(child))方法开始启动容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class{
child;
(child){
this.child=child;
}
@
Voidcall(){
//开始启动源码城,实际调用.()
child.start();
null;
}
}
.()方法中的核心代码:
1
2
3
4
5
6
7
8
void(type,data){
event=new(this,type,data);
//在方法的第一步中,设置的监听的对象
for(:){
//这里调用的是的()方法
.(event);
}
}
进入到中的()方法
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
void(event){
//thewearewith
try{
=()event.();
}catch(e){
log.error(sm.("e",event.()),e);
;
}
//theeventthathas
if(event.().(.T)){
//完成web.xml的内容解析
();
}elseif(event.().(.)){
();
}elseif(event.().(.)){
//fortools
if(!=null){
.();
}
}elseif(event.().(.)){
();
}elseif(event.().(.)){
init();
}elseif(event.().(.)){
();
}
}
在上面方法中,完成对web.xml的加载和解析,同时加载xml中配置的并且封装成对象。
3)、启动容器源码城,.()中的(())方法
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
35
36
37
38
39
40
41
42
([]){
//"loadon"thatneedtobe
>map=new();
for(child:){
//这里的就是我们前面封装的
=()child;
int=.();
if(
;
}
key=.();
list=map.get(key);
if(list==null){
list=new();
map.put(key,list);
}
list.add();
}
//Loadthe"loadon"
for(list:map.()){
for(:list){
try{
//通过load方法最终会调用的init方法
.load();
}catch(e){
().error(sm.("..",
(),.()),.(e));
//NOTE:load(athat
//fromtheinit())areNOT
//fatalto
//="true"is
if(()){
false;
}
}
}
}
true;
}
通过load方法最终会调用的init方法。
五、总结
上面内容就是整个是如何调用初始化方法的流程,整个流程小编的理解 |
【天外神坛】免责声明及帮助
1.重要:如果遇到隐藏内容回复后显示为代码状态,直接刷新一下页面即可解决此问题。
2.本文部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
3.若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4.如果本站有侵犯、不妥之处的资源,请在网站右边客服联系我们。将会第一时间解决!
5.本站所有内容均由互联网收集整理、网友上传,仅供大家参考、学习,不存在任何商业目的与商业用途。
6.本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
|