本文接下來描述servlet容器是怎樣管理其相關組件的生命周期的,首先本人描述一下事件監聽模式,也可以稱為觀察者模式,該模式分為以下角色
即抽象主題角色 具體主題角色 抽象觀察者角色及具體觀察者角色,通常在主題角色里面維持一個觀察者角色的聚集,并定義了對觀察者角色的添加和刪除方法;在主題角色事件發生時,通過迭代向這些觀察者角色發布事件。
在tomcat容器中,管理其相關組件的生命周期即是基于事件監聽模式實現的,相關接口和類為org.apache.catalina.Lifecycle接口、org.apache.catalina.LifecycleListener接口、org.apache.catalina.LifecycleEvent類
org.apache.catalina.Lifecycle接口定義如下
public
interface
Lifecycle {
public
static
final
String START_EVENT = "start"
;
public
static
final
String BEFORE_START_EVENT = "before_start"
;
public
static
final
String AFTER_START_EVENT = "after_start"
;
public
static
final
String STOP_EVENT = "stop"
;
public
static
final
String BEFORE_STOP_EVENT = "before_stop"
;
public
static
final
String AFTER_STOP_EVENT = "after_stop"
;
public
void
addLifecycleListener(LifecycleListener listener);
public
LifecycleListener[] findLifecycleListeners();
public
void
removeLifecycleListener(LifecycleListener listener);
public
void
start()
throws
LifecycleException;
public
void
stop()
throws
LifecycleException;
}
上面的六個靜態字符串代表六種類型的事件,接著的三個方法addLifecycleListener()、 findLifecycleListeners()、removeLifecycleListener()為與事件監聽器相關的,最后的兩個方法start()和stop()為啟動與關閉操作,組件必須提供這兩種方法的實現,供其父組件調用。
org.apache.catalina.LifecycleEvent類用于傳遞事件及攜帶事件數據
public
final
class
LifecycleEvent
extends
EventObject {
public
LifecycleEvent(Lifecycle lifecycle, String type) {
this
(lifecycle, type,
null
);
}
public
LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super
(lifecycle);
this
.lifecycle =
lifecycle;
this
.type =
type;
this
.data =
data;
}
private
Object data =
null
;
private
Lifecycle lifecycle =
null
;
private
String type =
null
;
public
Object getData() {
return
(
this
.data);
}
public
Lifecycle getLifecycle() {
return
(
this
.lifecycle);
}
public
String getType() {
return
(
this
.type);
}
}
org.apache.catalina.LifecycleListener為監聽器接口
public
interface
LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
*
*
@param
event LifecycleEvent that has occurred
*/
public
void
lifecycleEvent(LifecycleEvent event);
}
通常實現了Lifecycle接口并且對某個事件注冊了監聽器的組件必須提供 Lifecycle接口中三個與監聽器相關方法(分別為addLifecycleListener()、 findLifecycleListeners()、removeLifecycleListener())的實現,然后該組件需要將所有注冊的監聽器存儲到數組、ArrayList或者其他類似的對象中;tomcat容器提供了一個工具類org.apache.catalina.util.LifecycleSupport來幫助組件管理監聽器,并觸發相應的生命周期事件。
public
final
class
LifecycleSupport {
public
LifecycleSupport(Lifecycle lifecycle) {
super
();
this
.lifecycle =
lifecycle;
}
private
Lifecycle lifecycle =
null
;
private
LifecycleListener listeners[] =
new
LifecycleListener[0
];
public
void
addLifecycleListener(LifecycleListener listener) {
synchronized
(listeners) {
LifecycleListener results[]
=
new
LifecycleListener[listeners.length + 1
];
for
(
int
i = 0; i < listeners.length; i++
)
results[i]
=
listeners[i];
results[listeners.length]
=
listener;
listeners
=
results;
}
}
public
LifecycleListener[] findLifecycleListeners() {
return
listeners;
}
public
void
fireLifecycleEvent(String type, Object data) {
LifecycleEvent event
=
new
LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[]
=
null
;
synchronized
(listeners) {
interested
=
(LifecycleListener[]) listeners.clone();
}
for
(
int
i = 0; i < interested.length; i++
)
interested[i].lifecycleEvent(event);
}
public
void
removeLifecycleListener(LifecycleListener listener) {
synchronized
(listeners) {
int
n = -1
;
for
(
int
i = 0; i < listeners.length; i++
) {
if
(listeners[i] ==
listener) {
n
=
i;
break
;
}
}
if
(n < 0
)
return
;
LifecycleListener results[]
=
new
LifecycleListener[listeners.length - 1
];
int
j = 0
;
for
(
int
i = 0; i < listeners.length; i++
) {
if
(i !=
n)
results[j
++] =
listeners[i];
}
listeners
=
results;
}
}
}
下面我們來看Context容器(SimpleContext實例)是怎么實現生命周期管理及觸發監聽器事件的,關鍵代碼如下
public
class
SimpleContext
implements
Context, Pipeline, Lifecycle {
protected
LifecycleSupport lifecycle =
new
LifecycleSupport(
this
);
//
implementation of the Lifecycle interface's methods
public
void
addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
public
LifecycleListener[] findLifecycleListeners() {
return
null
;
}
public
void
removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
public
synchronized
void
start()
throws
LifecycleException {
if
(started)
throw
new
LifecycleException("SimpleContext has already started"
);
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT,
null
);
started
=
true
;
try
{
//
Start our subordinate components, if any
if
((loader !=
null
) && (loader
instanceof
Lifecycle))
((Lifecycle) loader).start();
//
Start our child containers, if any
Container children[] =
findChildren();
for
(
int
i = 0; i < children.length; i++
) {
if
(children[i]
instanceof
Lifecycle)
((Lifecycle) children[i]).start();
}
//
Start the Valves in our pipeline (including the basic),
//
if any
if
(pipeline
instanceof
Lifecycle)
((Lifecycle) pipeline).start();
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT,
null
);
}
catch
(Exception e) {
e.printStackTrace();
}
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT,
null
);
}
public
void
stop()
throws
LifecycleException {
if
(!
started)
throw
new
LifecycleException("SimpleContext has not been started"
);
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT,
null
);
lifecycle.fireLifecycleEvent(STOP_EVENT,
null
);
started
=
false
;
try
{
//
Stop the Valves in our pipeline (including the basic), if any
if
(pipeline
instanceof
Lifecycle) {
((Lifecycle) pipeline).stop();
}
//
Stop our child containers, if any
Container children[] =
findChildren();
for
(
int
i = 0; i < children.length; i++
) {
if
(children[i]
instanceof
Lifecycle)
((Lifecycle) children[i]).stop();
}
if
((loader !=
null
) && (loader
instanceof
Lifecycle)) {
((Lifecycle) loader).stop();
}
}
catch
(Exception e) {
e.printStackTrace();
}
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT,
null
);
}
}
Context容器實例持有對LifecycleSupport lifecycle = new LifecycleSupport(this)的引用,與事件監聽器相關方法均為操作該實例的相應方法
在其與生命周期相關方法start()和stop()方法里面,分別調用相關組件的生命周期方法,并采用LifecycleSupport lifecycle引用發布事件
一個簡單的監聽器實現如下:
public
class
SimpleContextLifecycleListener
implements
LifecycleListener {
public
void
lifecycleEvent(LifecycleEvent event) {
Lifecycle lifecycle
=
event.getLifecycle();
System.out.println(
"SimpleContextLifecycleListener's event " +
event.getType().toString());
if
(Lifecycle.START_EVENT.equals(event.getType())) {
System.out.println(
"Starting context."
);
}
else
if
(Lifecycle.STOP_EVENT.equals(event.getType())) {
System.out.println(
"Stopping context."
);
}
}
}
子容器wrapper實例(SimpleWrapper),同樣實現了Lifecycle接口,其相關實現與Context容器類似
public
class
SimpleWrapper
implements
Wrapper, Pipeline, Lifecycle {
protected
LifecycleSupport lifecycle =
new
LifecycleSupport(
this
);
//
implementation of the Lifecycle interface's methods
public
void
addLifecycleListener(LifecycleListener listener) {
}
public
LifecycleListener[] findLifecycleListeners() {
return
null
;
}
public
void
removeLifecycleListener(LifecycleListener listener) {
}
public
synchronized
void
start()
throws
LifecycleException {
System.out.println(
"Starting Wrapper " +
name);
if
(started)
throw
new
LifecycleException("Wrapper already started"
);
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT,
null
);
started
=
true
;
//
Start our subordinate components, if any
if
((loader !=
null
) && (loader
instanceof
Lifecycle))
((Lifecycle) loader).start();
//
Start the Valves in our pipeline (including the basic), if any
if
(pipeline
instanceof
Lifecycle)
((Lifecycle) pipeline).start();
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT,
null
);
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT,
null
);
}
public
void
stop()
throws
LifecycleException {
System.out.println(
"Stopping wrapper " +
name);
//
Shut down our servlet instance (if it has been initialized)
try
{
instance.destroy();
}
catch
(Throwable t) {
}
instance
=
null
;
if
(!
started)
throw
new
LifecycleException("Wrapper " + name + " not started"
);
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT,
null
);
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(STOP_EVENT,
null
);
started
=
false
;
//
Stop the Valves in our pipeline (including the basic), if any
if
(pipeline
instanceof
Lifecycle) {
((Lifecycle) pipeline).stop();
}
//
Stop our subordinate components, if any
if
((loader !=
null
) && (loader
instanceof
Lifecycle)) {
((Lifecycle) loader).stop();
}
//
Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT,
null
);
}
}
其他相關組件的相關實現不再贅述
---------------------------------------------------------------------------?
本系列How Tomcat Works系本人原創?
轉載請注明出處 博客園 刺猬的溫馴?
本人郵箱: ? chenying998179 # 163.com ( #改為@ )
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

