EventBus in-depth study 1
> EventBus is a message bus, which is implemented in the observer mode. It is used to simplify the communication between components and threads. It can easily switch threads and open threads. Traditionally, event distribution in Java process is realized through explicit registration between publishers and subscribers. EventBus is designed to replace this display registration method, so that there is a better decoupling between components. EventBus is not a generic publish-subscribe implementation and is not suitable for inter-process communication
order
Before we start, let's think about what the publish-subscribe model is and how to deal with it if we want to design a framework for the publish-subscribe model ourselves.
Let me give you a small example of my understanding.
There is a piggy bank in which the elders put money (1 wool, 5 wool, 1 yuan, 5 yuan, 10 yuan, 20 yuan, 50 yuan, 100 yuan) into it, and the younger generation draws money from it; somewhat different from the reality, each elder can only invest the same amount of money, while the younger generation can only get the same amount of money. Suppose Xiao Hong, Xiao Ming and Xiao Gang took 10 yuan from each other. Now Zhang San put 10 yuan into the bank and gave it to these three people on his own initiative, no matter what they did. (Unlike reality, Zhang San only guarded against 10 yuan, but Xiao Hong, Xiao Ming and Xiao Gang all got 10 yuan.)
The business process of this business is as follows:
- Three roles: publisher (elder), storage channel (money jar), subscriber (younger);
- Publishers will send messages to message pipelines
- Pipelines push messages to subscribers
Design:
- Publisher: Any person who publishes a message
- Message Pipeline: Bridge between Publisher and Subscriber. There are two main functions. One is to receive the message published by Publisher; the other is to push the message to Subscriber.
- Maintaining a subscriber relationship (message - > subscriber) requires an open registered interface for subscribers
- Accept the publisher to send messages, so you need to open an interface for publishers to publish messages
- Push the message to the subscriber. (This calls the subscriber's message acceptance callback method to achieve message push)
- Subscriber: Each subscriber, pays attention to and processes a message type.
- To become a subscriber, register with the message pipeline first (informing the type of consumer information and receiving the callback method of the message)
- Callback method for receiving messages (that is, the body that executes business logic after receiving messages)

Use
It's very simple to use, create an EventBus instance, subscriber, call EventBus.register() method to register, message publisher, call EvetBus. post (event); to publish a message, then subscribe class, add @subscribe annotation method will receive the message.
Examples are as follows:
/** * Messages sent */ @ToString @Getter @Setter public class AuditEvent { /** * Auditor */ private String auditUser; /** * Audit records */ private String record; /** * findings of audit */ private AuditEventEnum auditResultEnum; public enum AuditEventEnum { ACCEPT, REJECT, RETRY; } }
Subscriber
/** * First Inspection & amp; Review Monitor * <p/> * Created by yihui on 2017/3/1. */ @Component public class AuditEventListener { private static final Logger logger = LoggerFactory.getLogger(AuditEventListener.class); /** * Registration Events */ @PostConstruct public void init() { ActionEventBus.register(this); } /** * When the audit is completed, a message will be sent * <p/> * 1. Pass the audit * 2. Refusal of audit * 3. Re-examination * <p/> * Make different action s according to the message * * @param args */ @Subscribe public void invoke(AuditEvent args) { if (args.getAuditResultEnum() == AuditEvent.AuditEventEnum.ACCEPT) { System.out.println(1111); logger.info("Audit and approval!!!! {}", args.getRecord()); } else if (args.getAuditResultEnum() == AuditEvent.AuditEventEnum.REJECT) { System.out.println(2222); logger.info("Audit rejection!!!! {}", args.getRecord()); } else { logger.info("Re-examination!!!! {}", args.getRecord()); } } }
EventBus Manages Factory
public class ActionEventBus { private final static EventBus eventBus = new EventBus(); public static void post(Object event) { eventBus.post(event); } public static void register(Object handler) { eventBus.register(handler); } public static void unregister(Object handler) { eventBus.unregister(handler); } }
Publish news
@Test public void testAudit() { AuditEvent auditEvent = new AuditEvent(); auditEvent.setAuditResultEnum(AuditEvent.AuditEventEnum.ACCEPT); auditEvent.setAuditUser("1hui"); auditEvent.setRecord("test1"); // Publish a Successful Message ActionEventBus.post(auditEvent); auditEvent.setAuditResultEnum(AuditEvent.AuditEventEnum.REJECT); auditEvent.setAuditUser("2hui"); auditEvent.setRecord("test2"); // Publish a rejection message ActionEventBus.post(auditEvent); BuyEvent buyEvent = new BuyEvent(); buyEvent.setBuyerUser("3hui"); buyEvent.setCount(1); buyEvent.setTotalPrice(10000L); buyEvent.setItem("java book"); buyEvent.setBuyEventEnum(BuyEventEnum.PAY); ActionEventBus.post(buyEvent); System.out.println("over"); }
Analysis
> Note that we first take EventBus in google's Guava as the research object; we will use a lot of green robots/EventBus on android platform in the future.
From the above usage, we can see that EventBus is basically a message-subscription model, but the design is very clever.
From the subscriber's point of view, the first thing is to register. There's nothing to say. The key point is how to process messages.
- Adding a comment specifying the type of message reception (that is, the parameter type) allows you to accept such messages - Based on the above approach, a subscriber can subscribe to multiple different message sources
From the point of view of the message publisher, calling EventBus.post() directly, even if it is to publish a message, is extremely simple to use.
EventBus serves as a bridge of communication, which is what we call the "money tank" above. If you want to achieve asynchronous message processing, you can use Async EventBus directly.
From the above usage point of view, it greatly simplifies the process of usage, and can hardly be more easy; the only regret is that if asynchrony is found in the description above, it will be a bit troublesome to change to Async EventBus. If you can add a logo directly to the @subscribe annotation, it will be perfect to use asynchronous consumption.
preparation in advance
> Before we really get into source code analysis, let's do some preparatory work to understand the basic terminology and background.
1. Listeners
That is, our subscribers above ultimately accept events and execute the body of the business logic of the response.
Call the EventBus.register(Object) method on the EventBus instance to register event listeners; note that ensure that event producers and listeners share the same EventBus instance
2. Producers
The subject of the event is sent by passing the event to the EventBus.post(Object) method. Asynchronous distribution can directly use AsyncEventBus, a subclass of EventBus.
3. Terminology
term | Explain |
---|---|
Event | Objects that can be published to event bus |
Subscribe | Registering listeners to event buses to accept events |
monitor | Provides a processing method for objects that want to accept and process events |
processing method | The public method provided by the listener, which is used by the event bus to send events to the listener; the method should be annotated with Subscribe |
Publish news | Provide events to all matching listeners via event bus |