最近在學習spring框架源碼,看到了其中涉及事件處理,打算研究下事件的實現(xiàn)方式放刨,所以從頭學起,研究java中的事件實現(xiàn)機制尸饺。而且現(xiàn)實應用中很多都需要使用事件機制进统,而且使用事件機制也能對應用進行一定程度解耦。所以有必要好好了解下java中的事件機制浪听。
場景假設
我們以網(wǎng)購12306火車票為場景螟碎,假設以下一些操作。
用戶購買火車票成功后迹栓,會觸發(fā)發(fā)送短信操作告知用戶買了哪個車的票掉分。
用戶購買火車票成功后,會觸發(fā)發(fā)送郵件操作告知用戶買了哪個車的票克伊。
重點理解
針對上面的場景酥郭,我們分析可以有如下幾個對象或操作。
1.火車票對象答毫,2.購買成功發(fā)短信操作褥民,3.購買成功發(fā)郵件操作。
事件概念理解:
事件源:觸發(fā)事件的對象洗搂,例如購買火車票成功后發(fā)短信的火車票就是就是事件源消返。
事件:對事件源進行操作產生的事件载弄,例如購買成功后會產生發(fā)短信事件和發(fā)郵件事件。
事件監(jiān)聽器:對事件源產生的事件進行處理撵颊,可以對不同的事件設置不同的事件監(jiān)聽器宇攻,處理不同事件。
事件派發(fā)器:事件派發(fā)器主要處理事件的派發(fā)和事件監(jiān)聽器的管理倡勇,注冊和刪除事件監(jiān)聽器等逞刷。
目前java中EventObject對應事件,提供事件的基類妻熊,任何自定義事件都集成自該類夸浅;
EventListener對應事件監(jiān)聽器,提供事件監(jiān)聽器者接口扔役,任何自定義的事件監(jiān)聽器都實現(xiàn)了該接口帆喇。
事件派發(fā)器java中沒有提供,需要自己去實現(xiàn)亿胸。
自己寫代碼實現(xiàn)
以網(wǎng)購火車票為例坯钦,整體代碼結構如圖
TrainTicket事件源類
package me.wiliam;
/**
* 事件源類
* @author wiliam
*
*/
public class TrainTicket {
private String userName;
private String ticketName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getTicketName() {
return ticketName;
}
public void setTicketName(String ticketName) {
this.ticketName = ticketName;
}
}
TrainTicketEvent購票事件基類
package me.wiliam;
import java.util.EventObject;
/**
* 購票事件基類
* @author wiliam
*
*/
public class TrainTicketEvent extends EventObject {
private static final long serialVersionUID = 1L;
public TrainTicketEvent(TrainTicket source) {
super(source);
}
}
SendEmailEvent發(fā)送郵件事件
package me.wiliam;
/**
* 發(fā)送郵件事件
* @author wiliam
*
*/
public class SendEmailEvent extends TrainTicketEvent {
private static final long serialVersionUID = 1L;
private TrainTicket trainTicket;
public SendEmailEvent(TrainTicket source) {
super(source);
this.trainTicket = source;
}
public TrainTicket getTrainTicket(){
return trainTicket;
}
public String getEmailData(){
if(trainTicket != null){
String data = "發(fā)送郵件:"+trainTicket.getUserName() + "您好,您已成功購買火車票"+trainTicket.getTicketName();
return data;
}
return "";
}
}
SendSMSEvent發(fā)送短信事件
package me.wiliam;
/**
* 發(fā)送短信事件
* @author huhailong
*
*/
public class SendSMSEvent extends TrainTicketEvent {
private static final long serialVersionUID = 1L;
private TrainTicket trainTicket;
public SendSMSEvent(TrainTicket source) {
super(source);
this.trainTicket = source;
}
public TrainTicket getTrainTicket(){
return trainTicket;
}
public String getSMSData(){
if(trainTicket != null){
String data = "發(fā)送短信:"+trainTicket.getUserName() + "您好侈玄,您已成功購買火車票"+trainTicket.getTicketName();
return data;
}
return "";
}
}
TrainTicketListener火車票事件監(jiān)聽器接口
package me.wiliam;
import java.util.EventListener;
/**
* 火車票事件監(jiān)聽器接口
* @author wiliam
*
*/
public interface TrainTicketListener extends EventListener {
void handEvent(TrainTicketEvent tte);
}
EmailAndSMSListener同時處理發(fā)送郵件事件和短信事件
package me.wiliam;
/**
* 同時處理發(fā)送郵件事件和短信事件
* @author wiliam
*
*/
public class EmailAndSMSListener implements TrainTicketListener {
@Override
public void handEvent(TrainTicketEvent tte) {
if(tte instanceof SendEmailEvent){
SendEmailEvent see = (SendEmailEvent)tte;
System.out.println(see.getEmailData());
}else if(tte instanceof SendSMSEvent){
SendSMSEvent sse = (SendSMSEvent)tte;
System.out.println(sse.getSMSData());
}else{
System.out.println("發(fā)送未知事件婉刀,無法處理");
}
}
}
config.properties配置文件
#靈活使用監(jiān)聽器,多個可以用逗號間隔
listener=me.wiliam.EmailAndSMSListener
TestBuyTrainTicketSuccessEvent事件測試類
package me.wiliam;
/**
* 事件測試類
* @author wiliam
*
*/
public class TestBuyTrainTicketSuccessEvent {
public static void main(String[] args) {
TestBuyTrainTicketSuccessEvent tbtts = new TestBuyTrainTicketSuccessEvent();
tbtts.buySuccessTicket();
}
private void buySuccessTicket(){
TrainTicket tt = new TrainTicket();
tt.setTicketName("【北京---濟南】");
tt.setUserName("小明");
System.out.println("購票成功");
TrainTicketPublisher.instance().publishEvent(new SendEmailEvent(tt));
TrainTicketPublisher.instance().publishEvent(new SendSMSEvent(tt));
}
}
運行上面的測試類序仙,結果如下:
購票成功
發(fā)送郵件:小明您好突颊,您已成功購買火車票【北京---濟南】
發(fā)送短信:小明您好,您已成功購買火車票【北京---濟南】
思考
首先如果想要增加其它的監(jiān)聽器诱桂,在配置文件中配置下就可以了洋丐。
針對上面的事件發(fā)布器中對事件監(jiān)聽的處理完全可以單獨啟動一個線程,一直監(jiān)聽事件隊列挥等,有事件消息就處理友绝,這樣就可以即時響應各種消息了,解耦一定的程序模塊肝劲。
代碼下載
代碼已上傳到我的github上:https://github.com/wiliam2015/EventDemo
想了解更多技術文章信息迁客,請繼續(xù)關注wiliam.s Blog,謝謝辞槐,歡迎來訪掷漱!