guava实现事件驱动

Guava的EventBus可以简化生产/消费模型。EventBus通过非常简单的方式,实现了观察者模式中的监听注册,事件分发。有了这个玩意,真的可以替换Observer模式了

 

Observer模式是比较常用的设计模式之一,虽然有时候在具体代码里,它不一定叫这个名字,比如改头换面叫个Listener,但模式就是这个模式。手工实现一个Observer也不是多复杂的一件事,只是因为这个设计模式实在太常用了,Java就把它放到了JDK里面:Observable和Observer,从JDK 1.0里,它们就一直在那里。从某种程度上说,它简化了Observer模式的开发,至少我们不用再手工维护自己的Observer列表了。不过,如前所述,JDK里的Observer从1.0就在那里了,直到Java 7,它都没有什么改变,就连通知的参数还是Object类型。要知道,Java 5就已经泛型了。Java 5是一次大规模的语法调整,许多程序库从那开始重新设计了API,使其更简洁易用。当然,那些不做应对的程序库,多半也就过时了。这也就是这里要讨论知识更新的原因所在。今天,对于普通的应用,如果要使用Observer模式该如何做呢?答案是Guava的EventBus。

 

import com.google.common.eventbus.DeadEvent;

import com.google.common.eventbus.Subscribe;

 

EventBus基本用法:

 

  使用Guava之后, 如果要订阅消息, 就不用再继承指定的接口, 只需要在指定的方法上加上@Subscribe注解即可。代码如下:

 

  消息封装类:

Java代码   收藏代码
  1. public class TestEvent {  
  2.     private final int message;  
  3.     public TestEvent(int message) {          
  4.         this.message = message;  
  5.         System.out.println("event message:"+message);  
  6.     }  
  7.     public int getMessage() {  
  8.         return message;  
  9.     }  
  10. }  
public class TestEvent {
    private final int message;
    public TestEvent(int message) {        
        this.message = message;
        System.out.println("event message:"+message);
    }
    public int getMessage() {
        return message;
    }
}

 

  消息接受类:

Java代码   收藏代码
  1. public class EventListener {  
  2.     public int lastMessage = 0;  
  3.   
  4.     @Subscribe  
  5.     public void listen(TestEvent event) {  
  6.         lastMessage = event.getMessage();  
  7.         System.out.println("Message:"+lastMessage);  
  8.     }  
  9.   
  10.     public int getLastMessage() {        
  11.         return lastMessage;  
  12.     }  
  13. }  
public class EventListener {
    public int lastMessage = 0;

    @Subscribe
    public void listen(TestEvent event) {
        lastMessage = event.getMessage();
        System.out.println("Message:"+lastMessage);
    }

    public int getLastMessage() {      
        return lastMessage;
    }
}

 

  测试类及输出结果:

Java代码   收藏代码
  1. public class TestEventBus {  
  2.     @Test  
  3.     public void testReceiveEvent() throws Exception {  
  4.   
  5.         EventBus eventBus = new EventBus("test");  
  6.         EventListener listener = new EventListener();  
  7.   
  8.         eventBus.register(listener);  
  9.   
  10.         eventBus.post(new TestEvent(200));  
  11.         eventBus.post(new TestEvent(300));  
  12.         eventBus.post(new TestEvent(400));  
  13.   
  14.         System.out.println("LastMessage:"+listener.getLastMessage());  
  15.         ;  
  16.     }  
  17. }  
public class TestEventBus {
    @Test
    public void testReceiveEvent() throws Exception {

        EventBus eventBus = new EventBus("test");
        EventListener listener = new EventListener();

        eventBus.register(listener);

        eventBus.post(new TestEvent(200));
        eventBus.post(new TestEvent(300));
        eventBus.post(new TestEvent(400));

        System.out.println("LastMessage:"+listener.getLastMessage());
        ;
    }
}

 

//输出信息

event message:200

Message:200

event message:300

Message:300

event message:400

Message:400

LastMessage:400

 

   MultiListener的使用:

  只需要在要订阅消息的方法上加上@Subscribe注解即可实现对多个消息的订阅,代码如下:

Java代码   收藏代码
  1. public class MultipleListener {  
  2.     public Integer lastInteger;    
  3.     public Long lastLong;    
  4.      
  5.     @Subscribe    
  6.     public void listenInteger(Integer event) {    
  7.         lastInteger = event;   
  8.         System.out.println("event Integer:"+lastInteger);  
  9.     }    
  10.      
  11.     @Subscribe    
  12.     public void listenLong(Long event) {    
  13.         lastLong = event;   
  14.         System.out.println("event Long:"+lastLong);  
  15.     }    
  16.      
  17.     public Integer getLastInteger() {    
  18.         return lastInteger;    
  19.     }    
  20.      
  21.     public Long getLastLong() {    
  22.         return lastLong;    
  23.     }    
  24. }  
public class MultipleListener {
    public Integer lastInteger;  
    public Long lastLong;  
   
    @Subscribe  
    public void listenInteger(Integer event) {  
        lastInteger = event; 
        System.out.println("event Integer:"+lastInteger);
    }  
   
    @Subscribe  
    public void listenLong(Long event) {  
        lastLong = event; 
        System.out.println("event Long:"+lastLong);
    }  
   
    public Integer getLastInteger() {  
        return lastInteger;  
    }  
   
    public Long getLastLong() {  
        return lastLong;  
    }  
}

 

  测试类:

Java代码   收藏代码
  1. public class TestMultipleEvents {  
  2.     @Test    
  3.     public void testMultipleEvents() throws Exception {    
  4.          
  5.         EventBus eventBus = new EventBus("test");    
  6.         MultipleListener multiListener = new MultipleListener();    
  7.          
  8.         eventBus.register(multiListener);    
  9.          
  10.         eventBus.post(new Integer(100));  
  11.         eventBus.post(new Integer(200));    
  12.         eventBus.post(new Integer(300));    
  13.         eventBus.post(new Long(800));   
  14.         eventBus.post(new Long(800990));    
  15.         eventBus.post(new Long(800882934));    
  16.          
  17.         System.out.println("LastInteger:"+multiListener.getLastInteger());  
  18.         System.out.println("LastLong:"+multiListener.getLastLong());  
  19.     }     
  20. }  
public class TestMultipleEvents {
    @Test  
    public void testMultipleEvents() throws Exception {  
       
        EventBus eventBus = new EventBus("test");  
        MultipleListener multiListener = new MultipleListener();  
       
        eventBus.register(multiListener);  
       
        eventBus.post(new Integer(100));
        eventBus.post(new Integer(200));  
        eventBus.post(new Integer(300));  
        eventBus.post(new Long(800)); 
        eventBus.post(new Long(800990));  
        eventBus.post(new Long(800882934));  
       
        System.out.println("LastInteger:"+multiListener.getLastInteger());
        System.out.println("LastLong:"+multiListener.getLastLong());
    }   
}

 

//输出信息

event Integer:100

event Integer:200

event Integer:300

event Long:800

event Long:800990

event Long:800882934

LastInteger:300

LastLong:800882934

 

  Dead Event:

  如果EventBus发送的消息都不是订阅者关心的称之为Dead Event。实例如下:

Java代码   收藏代码
  1. public class DeadEventListener {  
  2.     boolean notDelivered = false;    
  3.          
  4.     @Subscribe    
  5.     public void listen(DeadEvent event) {    
  6.           
  7.         notDelivered = true;    
  8.     }    
  9.      
  10.     public boolean isNotDelivered() {    
  11.         return notDelivered;    
  12.     }    
  13. }  
public class DeadEventListener {
    boolean notDelivered = false;  
       
    @Subscribe  
    public void listen(DeadEvent event) {  
        
        notDelivered = true;  
    }  
   
    public boolean isNotDelivered() {  
        return notDelivered;  
    }  
}

 

  测试类:

Java代码   收藏代码
  1. public class TestDeadEventListeners {  
  2.     @Test    
  3.     public void testDeadEventListeners() throws Exception {    
  4.          
  5.         EventBus eventBus = new EventBus("test");                 
  6.         DeadEventListener deadEventListener = new DeadEventListener();    
  7.         eventBus.register(deadEventListener);    
  8.   
  9.         eventBus.post(new TestEvent(200));           
  10.         eventBus.post(new TestEvent(300));          
  11.          
  12.         System.out.println("deadEvent:"+deadEventListener.isNotDelivered());  
  13.   
  14.     }    
  15. }  
public class TestDeadEventListeners {
    @Test  
    public void testDeadEventListeners() throws Exception {  
       
        EventBus eventBus = new EventBus("test");               
        DeadEventListener deadEventListener = new DeadEventListener();  
        eventBus.register(deadEventListener);  

        eventBus.post(new TestEvent(200));         
        eventBus.post(new TestEvent(300));        
       
        System.out.println("deadEvent:"+deadEventListener.isNotDelivered());

    }  
}

 

//输出信息

event message:200

event message:300

deadEvent:true

 

  说明:如果没有消息订阅者监听消息, EventBus将发送DeadEvent消息,这时我们可以通过log的方式来记录这种状态。

 

  Event的继承:

  如果Listener A监听Event A, 而Event A有一个子类Event B, 此时Listener A将同时接收Event A和B消息,实例如下:

 

  Listener 类:

Java代码   收藏代码
  1. public class NumberListener {    
  2.          
  3.     private Number lastMessage;    
  4.      
  5.     @Subscribe    
  6.     public void listen(Number integer) {    
  7.         lastMessage = integer;   
  8.         System.out.println("Message:"+lastMessage);  
  9.     }    
  10.      
  11.     public Number getLastMessage() {    
  12.         return lastMessage;    
  13.     }    
  14. }    
  15.   
  16. public class IntegerListener {    
  17.          
  18.     private Integer lastMessage;    
  19.      
  20.     @Subscribe    
  21.     public void listen(Integer integer) {    
  22.         lastMessage = integer;   
  23.         System.out.println("Message:"+lastMessage);  
  24.     }    
  25.      
  26.     public Integer getLastMessage() {    
  27.         return lastMessage;    
  28.     }    
  29. }    
public class NumberListener {  
       
    private Number lastMessage;  
   
    @Subscribe  
    public void listen(Number integer) {  
        lastMessage = integer; 
        System.out.println("Message:"+lastMessage);
    }  
   
    public Number getLastMessage() {  
        return lastMessage;  
    }  
}  

public class IntegerListener {  
       
    private Integer lastMessage;  
   
    @Subscribe  
    public void listen(Integer integer) {  
        lastMessage = integer; 
        System.out.println("Message:"+lastMessage);
    }  
   
    public Integer getLastMessage() {  
        return lastMessage;  
    }  
}  

 

  测试类:

Java代码   收藏代码
  1. public class TestEventsFromSubclass {  
  2.     @Test    
  3.     public void testEventsFromSubclass() throws Exception {    
  4.          
  5.         EventBus eventBus = new EventBus("test");    
  6.         IntegerListener integerListener = new IntegerListener();    
  7.         NumberListener numberListener = new NumberListener();    
  8.         eventBus.register(integerListener);    
  9.         eventBus.register(numberListener);    
  10.          
  11.         eventBus.post(new Integer(100));    
  12.          
  13.         System.out.println("integerListener message:"+integerListener.getLastMessage());  
  14.         System.out.println("numberListener message:"+numberListener.getLastMessage());  
  15.                 
  16.         eventBus.post(new Long(200L));    
  17.          
  18.         System.out.println("integerListener message:"+integerListener.getLastMessage());  
  19.         System.out.println("numberListener message:"+numberListener.getLastMessage());          
  20.     }    
  21. }  
public class TestEventsFromSubclass {
    @Test  
    public void testEventsFromSubclass() throws Exception {  
       
        EventBus eventBus = new EventBus("test");  
        IntegerListener integerListener = new IntegerListener();  
        NumberListener numberListener = new NumberListener();  
        eventBus.register(integerListener);  
        eventBus.register(numberListener);  
       
        eventBus.post(new Integer(100));  
       
        System.out.println("integerListener message:"+integerListener.getLastMessage());
        System.out.println("numberListener message:"+numberListener.getLastMessage());
              
        eventBus.post(new Long(200L));  
       
        System.out.println("integerListener message:"+integerListener.getLastMessage());
        System.out.println("numberListener message:"+numberListener.getLastMessage());        
    }  
}

 //输出类

Message:100

Message:100

integerListener message:100

numberListener message:100

Message:200

integerListener message:100

numberListener message:200

 

  说明:在这个方法中,我们看到第一个事件(新的整数(100))是收到两个听众,但第二个(新长(200 l))只能到达NumberListener作为整数一不是创建这种类型的事件。可以使用此功能来创建更通用的监听器监听一个广泛的事件和更详细的具体的特殊的事件。

 

   一个综合实例

Java代码   收藏代码
  1. public class UserThread extends Thread {  
  2.     private Socket connection;  
  3.     private EventBus channel;  
  4.     private BufferedReader in;  
  5.     private PrintWriter out;  
  6.   
  7.     public UserThread(Socket connection, EventBus channel) {  
  8.         this.connection = connection;  
  9.         this.channel = channel;  
  10.         try {  
  11.             in = new BufferedReader(new InputStreamReader(connection.getInputStream()));  
  12.             out = new PrintWriter(connection.getOutputStream(), true);  
  13.         } catch (IOException e) {  
  14.             e.printStackTrace();  
  15.             System.exit(1);  
  16.         }  
  17.     }  
  18.   
  19.     @Subscribe  
  20.     public void recieveMessage(String message) {  
  21.         if (out != null) {  
  22.             out.println(message);  
  23.             System.out.println("recieveMessage:"+message);  
  24.         }  
  25.     }  
  26.   
  27.     @Override  
  28.     public void run() {  
  29.         try {  
  30.             String input;  
  31.             while ((input = in.readLine()) != null) {  
  32.                 channel.post(input);  
  33.             }  
  34.         } catch (IOException e) {  
  35.             e.printStackTrace();  
  36.         }  
  37.           
  38.         //reached eof  
  39.         channel.unregister(this);  
  40.         try {  
  41.             connection.close();  
  42.         } catch (IOException e) {  
  43.             e.printStackTrace();  
  44.         }  
  45.         in = null;  
  46.         out = null;  
  47.     }  
  48. }  
public class UserThread extends Thread {
    private Socket connection;
    private EventBus channel;
    private BufferedReader in;
    private PrintWriter out;

    public UserThread(Socket connection, EventBus channel) {
        this.connection = connection;
        this.channel = channel;
        try {
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            out = new PrintWriter(connection.getOutputStream(), true);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Subscribe
    public void recieveMessage(String message) {
        if (out != null) {
            out.println(message);
            System.out.println("recieveMessage:"+message);
        }
    }

    @Override
    public void run() {
        try {
            String input;
            while ((input = in.readLine()) != null) {
                channel.post(input);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        //reached eof
        channel.unregister(this);
        try {
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        in = null;
        out = null;
    }
}

 

Java代码   收藏代码
  1. import java.io.IOException;  
  2. import java.net.ServerSocket;  
  3. import java.net.Socket;  
  4.   
  5. import com.google.common.eventbus.EventBus;  
  6.   
  7. public class EventBusChat {  
  8.     public static void main(String[] args) {  
  9.         EventBus channel = new EventBus();  
  10.         ServerSocket socket;  
  11.         try {  
  12.             socket = new ServerSocket(4444);  
  13.             while (true) {  
  14.                 Socket connection = socket.accept();  
  15.                 UserThread newUser = new UserThread(connection, channel);  
  16.                 channel.register(newUser);  
  17.                 newUser.start();  
  18.             }  
  19.         } catch (IOException e) {  
  20.             e.printStackTrace();  
  21.         }  
  22.     }  
  23. }  
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import com.google.common.eventbus.EventBus;

public class EventBusChat {
    public static void main(String[] args) {
        EventBus channel = new EventBus();
        ServerSocket socket;
        try {
            socket = new ServerSocket(4444);
            while (true) {
                Socket connection = socket.accept();
                UserThread newUser = new UserThread(connection, channel);
                channel.register(newUser);
                newUser.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

 

  说明:用telnet命令登录:telnet 127.0.0.1 4444 ,如果你连接多个实例你会看到任何消息发送被传送到其他实例。

 

另参考:Guava的生产/消费模型 —— EventBus


转载自:http://uule.iteye.com/blog/2096279

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值