一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Tomcat和Spring中的事件機制深入講解

Tomcat和Spring中的事件機制深入講解

2021-06-23 14:07knock_小新 Java教程

這篇文章主要給大家介紹了關于Tomcat和Spring中事件機制的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧

引言

最近在看tomcat源碼,源碼中出現了大量事件消息,可以說整個tomcat的啟動流程都可以通過事件派發機制串起來,研究透了tomcat的各種事件消息,基本上對tomcat的啟動流程也就有了一個整體的認識。在這一基礎上,聯想到之前在看spring源碼過程中也存在不少事件相關知識,于是想對這兩個框架中的事件派發機制做一個簡單的總結,加深理解。

事件機制原理其實比較簡單,抽象來看的話,設計模式中的觀察者模式可以說是最經典的事件驅動機制的體現了,觀察者和被觀察者就體現了事件監聽和事件派發的角色。還有各種mq,其實也是事件機制的一種體現。

理解tomcat和spring中的事件機制之前,讓我們先從最基本的jdk中提供的事件機制開始說起。

jdk中的事件機制

jdk中對事件機制的各個角色提供了完善的抽象,主要包括3個角色:

eventobject(事件關注內容):事件發布時需要關注的內容。jdk中提供了eventobject接口。

eventlistener(事件監聽者):事件監聽對象,也就是對eventobject感興趣的對象。jdk中提供了eventlistener接口。

eventsource(事件源):發布事件的對象,可以在該對象中組冊eventlistener,然后在特定的條件下發布eventobject給已經注冊的eventlistener。

事件的注冊與發布,需要這三個對象協同工作,可以通過下面的例子來說明各個對象的作用:

首先是事件關注內容對象myeventobject,實現了eventobject接口。eventname參數為具體的事件關注內容

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class myeventobject extends eventobject {
 
 private string eventname ;
 
 public myeventobject (object source, string eventname) {
  
  super(source);
  this.seteventname(eventname);
 }
 
 public string geteventname() {
  return eventname;
 }
 
 public void seteventname(string eventname) {
  this.eventname = eventname;
 }
 
 private static final long serialversionuid = 8374250957018011175l;
}

其次是事件監聽接口myeventlistener,繼承了eventlistener,定義了一個myevent接口用來發布事件,任何感興趣的監聽對象都可以實現該接口來監聽。

對myeventobject感興趣的監聽者myeventlistenerimpl,實現了myeventlistener接口,當事件發布時會觸發myevent事件并收到myeventobject對象。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface myeventlistener extends eventlistener {
 
 public void myevent(myeventobject eventobject);
}
 
public class myeventlistenerimpl implements myeventlistener {
 
 @override
 public void myevent(myeventobject eventobject) {
 
  system.out.println("myeventlistenerimpl --- " + eventobject.geteventname());
 }
}

最后是事件發布源對象myeventsource,它可以注冊多個事件監聽對象,任何實現了myeventlistener接口的監聽對象都可以注冊,內部通過一個set來存儲感興趣的監聽對象,并在合適的時機會發布消息并通知所有監聽對象。

?
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
public class myeventsource {
 
 private set<myeventlistener> myeventlisteners = new hashset<>();
 
 public void addlistener(myeventlistener listener){
  
  this.myeventlisteners.add(listener);
 }
 
 public void removelistener(myeventlistener listener){
  
  this.myeventlisteners.remove(listener);
 }
 
 public void pushevent(){
  //dosomething
  //發布push event消息
  notifylistener(new myeventobject(this, "push event"));
 }
 
 private void notifylistener(myeventobject eventobject){
  
  for (myeventlistener myeventlistener : myeventlisteners) {
   myeventlistener.myevent(eventobject);
  }
 }
}

之后可以通過一個啟動類來注冊并觸發事件:

?
1
2
3
4
5
6
7
8
9
10
public static void main(string[] args) {
 
 myeventsource myeventsource = new myeventsource();
 
 myeventlistenerimpl myeventlistenerimpl = new myeventlistenerimpl();
 
 myeventsource.addlistener(myeventlistenerimpl);
 
 myeventsource.pushevent();
}

myeventobject定義了感興趣的內容,myeventlistenerimpl是對myeventobject感興趣的監聽者,myeventsource會發布myeventobject給所有組冊的監聽者,最后通過一個main來啟動整個流程。

明白了jdk中對事件機制的定義,再來看看tomcat和spring中的事件機制。

tomcat的事件機制

tomcat的事件機制也離不開eventobject、eventlistener以及eventsource三個對象,只不過在此基礎上提供了更加抽象和便捷的操作。這里我挑選tomcat的生命周期接口對象lifecycle來講解整個事件發布流程:

首先還是eventobject對象lifecycleevent,這里只列出了核心代碼。它的主要參數是lifecycle,lifecycle中定義了tomcat各個階段的名稱:before_init、after_init、start等等,是事件監聽者感興趣的對象。

?
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
public final class lifecycleevent extends eventobject {
 
 //......
 
 public lifecycleevent(lifecycle lifecycle, string type, object data) {
 
  super(lifecycle);
  this.type = type;
  this.data = data;
 }
 
 //......
}
 
public interface lifecycle {
 /**
  * the lifecycleevent type for the "component after init" event.
  */
 public static final string before_init_event = "before_init";
 
 /**
  * the lifecycleevent type for the "component after init" event.
  */
 public static final string after_init_event = "after_init";
 
 /**
  * the lifecycleevent type for the "component start" event.
  */
 public static final string start_event = "start";
 
 //......
}

事件監聽接口lifecyclelistener,定義了lifecycleevent方法用來傳遞監聽者感興趣的lifecycleevent對象,監聽者使用lifecycleevent參數用來在tomcat的各個階段處理進行相應處理。這些感興趣的對象包括下面這些類:

Tomcat和Spring中的事件機制深入講解

這里使用contextconfig類為例,可以看到它實現了lifecyclelistener接口。這個類在解析server.xml的時候用來監聽standardcontext的各個階段的事件,并做出相應處理:

?
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
public interface lifecyclelistener {
 
 public void lifecycleevent(lifecycleevent event);
}
 
public class contextconfig implements lifecyclelistener {
 
 //......
 @override
 public void lifecycleevent(lifecycleevent event) {
 
  // identify the context we are associated with
  try {
   context = (context) event.getlifecycle();
  } catch (classcastexception e) {
   log.error(sm.getstring("contextconfig.cce", event.getlifecycle()), e);
   return;
  }
 
  // process the event that has occurred
  if (event.gettype().equals(lifecycle.configure_start_event)) {
   configurestart();
  } else if (event.gettype().equals(lifecycle.before_start_event)) {
   beforestart();
  } else if (event.gettype().equals(lifecycle.after_start_event)) {
   // restore docbase for management tools
   if (originaldocbase != null) {
    context.setdocbase(originaldocbase);
   }
  } else if (event.gettype().equals(lifecycle.configure_stop_event)) {
   configurestop();
  } else if (event.gettype().equals(lifecycle.after_init_event)) {
   init();
  } else if (event.gettype().equals(lifecycle.after_destroy_event)) {
   destroy();
  }
 }
 
 //......
}

lifecyclesupport是我們需要了解的主要對象,它是監聽對象的一個管理類,原理其實和上面的例子差不多,對應了myeventsource類的部分功能,方便eventsource類來管理監聽對象。它把對監聽對象的添加移除以及發布事件幾個操作進行了統一管理,避免eventsource類中出現太多管理監聽對象的邏輯。

?
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public final class lifecyclesupport {
 
 //......
 
 //監聽對象集合
 private lifecyclelistener listeners[] = new lifecyclelistener[0];
 
 private final object listenerslock = new object(); // lock object for changes to listeners
 
 //添加監聽對象
 public void addlifecyclelistener(lifecyclelistener listener) {
 
  synchronized (listenerslock) {
   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 void firelifecycleevent(string type, object data) {
 
  lifecycleevent event = new lifecycleevent(lifecycle, type, data);
  lifecyclelistener interested[] = listeners;
  for (int i = 0; i < interested.length; i++)
   interested[i].lifecycleevent(event);
 
 }
 
 //移除監聽對象
 public void removelifecyclelistener(lifecyclelistener listener) {
 
  synchronized (listenerslock) {
   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;
  }
 }
}

使用了lifecyclesupport之后,操作lifecyclelistener就簡單多了,只需要調用lifecyclesupport的各個方法就可以了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public abstract class lifecyclebase implements lifecycle{
 
 //......
 private lifecyclesupport lifecycle = new lifecyclesupport(this);
 
 @override
 public void addlifecyclelistener(lifecyclelistener listener) {
  lifecycle.addlifecyclelistener(listener);
 }
 
 @override
 public void removelifecyclelistener(lifecyclelistener listener) {
  lifecycle.removelifecyclelistener(listener);
 }
 
 protected void firelifecycleevent(string type, object data) {
  lifecycle.firelifecycleevent(type, data);
 }
 //......
}

在需要發布事件時調用firelifecycleevent方法就可以發布事件:

?
1
firelifecycleevent(lifecycle.configure_stop_event, null);

tomcat事件機制就是在之前的例子上抽出了一個lifecyclesupport類來方便管理監聽對象的各種操作,這是一個可以借鑒的地方,其他差別并不大。再來看看spring中對事件機制的處理。

spring的事件機制

spring中的事件機制原理也是一樣的,只是相對來說實現上稍微復雜一點。還是通過相同的角度來看這個問題。

首先是eventobject,spring里面的主要實現是applicationevent:

Tomcat和Spring中的事件機制深入講解

這里通過contextstartedevent類來查看eventobject,它關注的對象是applicationcontext,是spring容器在啟動時觸發的事件對象:

?
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
public abstract class applicationevent extends eventobject {
 
 //......
 public applicationevent(object source) {
  super(source);
  this.timestamp = system.currenttimemillis();
 }
 //......
}
 
public abstract class applicationcontextevent extends applicationevent {
 public applicationcontextevent(applicationcontext source) {
  super(source);
 }
 
 public final applicationcontext getapplicationcontext() {
  return (applicationcontext)this.getsource();
 }
}
 
public class contextstartedevent extends applicationcontextevent {
 public contextstartedevent(applicationcontext source) {
  super(source);
 }
}

事件監聽接口applicationlistener,定義了onapplicationevent方法用來傳遞監聽者感興趣的applicationevent對象,監聽者使用applicationevent參數用來在context的各個階段處理進行相應處理。

如果我們需要在容器啟動后進行相應處理,那么我們可以在業務類中實現applicationlistener接口,在事件發生時就會發起通知:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface applicationlistener<e extends applicationevent> extends eventlistener {
 
 void onapplicationevent(e event);
}
 
public class myapplicationlistener implements applicationlistener<applicationevent> {
 
 @override
 public void onapplicationevent(applicationevent applicationevent) {
 
  if (applicationevent instanceof contextrefreshedevent){
 
   system.out.println("context refresh!");
  }
 }
}

那么在spring框架中是怎么發布這些事件的呢?是不是也有一個類似tomcat中lifecyclesupport一樣的類呢?通過查看源碼可以發現發現,applicationcontext容器在初始化階段會調用refresh()方法,這其中又調用了
finishrefresh()方法,這其中調用了publishevent(new contextrefreshedevent(this))方法,發布了contextrefreshedevent這一對象。

?
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
protected void finishrefresh() {
 
 //......
 // publish the final event.
 publishevent(new contextrefreshedevent(this));
}
 
protected void publishevent(object event, @nullable resolvabletype eventtype) {
 
 //......
 getapplicationeventmulticaster().multicastevent(applicationevent, eventtype);
 //......
}
 
publishevent方法通過調用一個默認的多播器simpleapplicationeventmulticaster的multicastevent方法來發布各種事件:
 
simpleapplicationeventmulticaster
public void multicastevent(final applicationevent event, @nullable resolvabletype eventtype) {
 resolvabletype type = (eventtype != null ? eventtype : resolvedefaulteventtype(event));
 
 //通過getapplicationlisteners獲取了所有監聽器,然后通過invokelistener方法循環發布事件
 for (final applicationlistener<?> listener : getapplicationlisteners(event, type)) {
  executor executor = gettaskexecutor();
  if (executor != null) {
   executor.execute(() -> invokelistener(listener, event));
  }
  else {
   invokelistener(listener, event);
  }
 }
}
 
protected void invokelistener(applicationlistener<?> listener, applicationevent event) {
 //......
 doinvokelistener(listener, event);
}
 
private void doinvokelistener(applicationlistener listener, applicationevent event) {
 //......
 listener.onapplicationevent(event);
}

也就是說在spring容器中發布applicationlistener所關注的對象是通過simpleapplicationeventmulticaster這個類來管理的,和tomcat中lifecyclesupport的功能類似,只是在實現上有略微差別。

最后提一句,在spring中你也可以自己發布各種事件,調用applicationcontext的publishevent方法即可。

?
1
applicationcontext.publishevent(new applicationevent(new string("事件發布")) { });

總結

這篇文章對java的事件機制在tomcat以及spring框架中的實現做了一個簡單總結和對比,你需要知道以下幾點:

  • jdk中定義了eventobject和eventlistener兩個接口,奠定了事件機制的基礎。
  • tomcat額外提供了一個support類來對監聽器的添加刪除以及發布進行管理。
  • spring容器內部通過simpleapplicationeventmulticaster來發布各個事件,用戶可以通過實現applicationlistener接口來監聽自己感興趣的容器事件。

希望你通過這篇文章的學習可以對java的事件機制有一個更深刻的認識,在實現自己的事件機制時有可以借鑒以及改進的地方。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:http://www.cnblogs.com/konck/p/10134541.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产美女亚洲精品久久久综合 | 男女一级簧色带 | 99热6这里只有精品 99欧美精品 | 男人天堂资源网 | 手机在线观看国产精选免费 | xxoosex久久久久久 | 美日韩在线观看 | 国产亚洲精品看片在线观看 | 美女被躁爽死 | 美女下面被cao出水 美女污视频 | a4yy欧美一区二区三区 | 日韩一品在线播放视频一品免费 | 视频一区二区国产无限在线观看 | 91精品天美精东蜜桃传媒免费 | 男女交性特一级 | 大陆男男gayxxxxvideo | 天天操天天干天天做 | 精品一区二区三区高清免费观看 | 国产亚洲精品激情一区二区三区 | 91嫩草私人成人亚洲影院 | 久久草福利自拍视频在线观看 | 国产1区精品 | 青青草原在线免费 | 国产三级自拍 | 亚洲欧美在线免费观看 | 香蕉精品高清在线观看视频 | 精品国产免费 | 天天综合五月天 | 好姑娘在线视频观看免费 | 色婷婷激婷婷深爱五月老司机 | 成人免费一区二区三区在线观看 | 911亚洲精品国内自产 | 成人123| 美女的隐私视频免费看软件 | 国内视频一区二区 | 夫妻性生活在线 | 1024国产精品视频观看 | 欧美性色老妇人 | 午夜影视免费 | 成人免费一区二区三区在线观看 | 福利一区二区在线观看 |