Event monitoring mechanism
For those of you familiar with Spring, Spring provides a complete set of event monitoring mechanisms. To understand Spring, familiarize yourself with the Observer pattern. Java has had an observer pattern design since version 1.0. Let’s take a look at the observer pattern provided by Java through an example.
Observer model
The Observer mode consists of one Observable (subject observed) and multiple observers (Observer). All Observer objects are stored in the observed. When the observed receives an external message, all observers will be notified. This is essentially a topic change, and viewers who subscribe to it receive a message about it. (Also known as publish subscribe)JDK above is the class diagram for observer mode. Observer (Obsever), observed (Observable). It can be seen from the source code that the observed object will be maintained in the observed. After the observer registers in the observed list, the notice sent by the observed observer will receive changes. The unpdate (Observable, Object) method in the observer. By listening for changes to happen to the observed, to trigger a response from the observer. Simulate a scene of teacher and student: observed (teacher), observer (student).
Case 1.
The observer
public class MyObserver implements Observer {
/** * student name */
private String name;
public MyObserver(Observable o, String name) {
o.addObserver(this);
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println("Observer (student)" + name + "Homework received! "" + arg + "" "+"Number of observers of target ="+ o.countObservers()); }}Copy the code
The observed
public class MyObserverable extends Observable {
// Observed data
private String data;
public String getData(a) {
return data;
}
/** ** if yes if change *@param data
*/
public void setData(String data) {
// Change the change state
setChanged();
// Notify registered observersnotifyObservers(data); }}Copy the code
test
public static void main(String[] args) {
//1. Construct the observed object. (If the teacher in the real world)
MyObserverable observerable = new MyObserverable();
//2. Construct 2 observer implementation classes: Add the observer to the observation target (students in the real scene, each new student will be added to the teacher's observer directory)
MyObserver observer1 = new MyObserver(observerable, "tom");
MyObserver observer2 = new MyObserver(observerable, "jerry");
//3. The subject (teacher) announces today's homework. Its registered observers (students) responded.
observerable.setData("Java from entry to abandonment");
}
Copy the code
Results:
The observed is online at.... Observer (student) Jerry gets his homework! Number of observers for Java from Start to Quit target =2Observer (student) Tom gets his homework! Number of observers for Java from Start to Quit target =2
Copy the code
Observers == notifyObservers(data); ==, triggers message notification to observers. The observer sees a change and makes a change. ==update(Observable o, Object arg) {}==.
Spring event mechanism (event listener mechanism)
Through the above observer mode, we can understand the design patterns and ideas. Listener mode is similar in that it contains a Listener, Event, and EventPublish. EventPublish publishes an Event, which is caught by the Listener and processed accordingly. The event listener mechanism, in fact, has been in design mode since JDK 1.1, and its main base classes are event sourcesEventObject
And the listenerEventListener
, publisher (Spring)ApplicationEventPublisher
The following example demonstrates event publishing subscriptions.
Case 2.
Event source: Spring’s event source is ApplicationEvent, inherited from the EventObject base class provided by the JDK.
public class MyContextEvent extends ApplicationEvent {
public MyContextEvent(Object source) {
super(source);
System.out.println("source message->"+source.toString()); }}Copy the code
Listener: Spring’s listener is ApplicationListener, inherited from the EventListener interface provided by the JDK. There is no method definition in EventListener, just listener identification.
public class MyContextListener implements ApplicationListener<MyContextEvent> {
@Override
public void onApplicationEvent(MyContextEvent myContextEvent) {
System.out.println("listener this MyContextEvent...."); }}Copy the code
Here we use the Event publishing function of the Spring container to achieve this, automatically publishing and listening with the registration of events. In the event of the spring container to ConfigurableApplicationContext AbstractApplicationContext inheritance, ConfigurableApplicationContext class inheritance to the ApplicationContext. The core of the IOC container interface inherits the ApplicationContext, event publishing ApplicationEventPublisher. In its subclasses implement the parent interface in AbstractApplicationContext ApplicationEventPublisher publishEvent (ApplicationEvent event) method.
/ / AbstractApplicationContext publishEvent method in class. public void publishEvent(ApplicationEvent event) { this.publishEvent(event, (ResolvableType)null); }Copy the code
test
public static void main(String[] args) {
// Get the IOC container
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// Register listeners
context.register(MyContextListener.class);
// Refresh the container
context.refresh();
// Event release
context.publishEvent(new MyContextEvent("publish this event ...."));
}
Copy the code
The results of
source message->publish this event ....
listener this MyContextEvent....
Copy the code
In the IOC container, add listeners for custom events ==context.register(myContextListener.class); Publish custom events == context.publishevent (new MyContextEvent(“publish this event….”) )); == Custom message. The listener responds.
Integrate EventBus applications based on Springboot event listening mechanism
I covered the observer pattern and Spring’s event publishing mechanism. Through the way of case code, introduced. The following is a ground-based implementation of the Observer pattern, Google Guava’s EventBus event handling. EventBus does not need to implement complex events, listeners, and publishers. Only the API provided is needed to implement the event mechanism. Evnet is based on the event type published by the publisher, the listener subscribes to this event type, to publish the subscription pattern. When using EventBus, we simply pass the type of event we want to publish through the Public void POST (Object Event) method in the EventBus API. Listeners listen for events of a specified type with @Subscribe. The SpringBoot event mechanism is also implemented based on the Spring event mechanism. Spring event type of support in the boot in the org. Springframework. Boot. The context. The event package, springboot project start the loading process, Is done through EventPublishingRunListener springboot event trigger. The following six event types are supported.
- ApplicationStartedEvent Spring Boot starts the listener class
- ApplicationEnvironmentPreparedEvent prepared environment, the environment is ready to spring boot ok
- The ApplicationPreparedEvent context prepares the event
- The ApplicationReadyEvent context is ready and OK
- ApplicationFailedEvent This event is the operation when Spring Boot fails to start (an exception event occurs during startup).
- SpringApplicationEvent get SpringApplication
Each step of the loading process triggers a different event to complete the corresponding operation. I’m not going to go over springboot events here. Those of you who are interested can go through the startup categorySpringApplication.run(CommonApplication.class, args)
。SpringApplication
In the classrun
Method to study the whole startup process, what to do, this part of the online explanation is also a lot, post a springBoot startup process.The implementation of the EventBus API is not complicated. The following is an example of an event-driven project using springBoot’s event publishing mechanism. Start by understanding Spring’s event publishing mechanism, which integrates EventBus.
Thoughts and ideas: 1. Listen for the ApplicationPreparedEvent context to prepare the event through the Event loading mechanism of Springboot. When the context prepares the event, the listener of this event will be listened (implement ApplicationListener in Spring). Add to EventBus’s Event listener (the Event listener register(Object Handler)). 2. Add listeners of the subscriber (that is, implementing ApplicationListener listeners). Listen via the @subscrib annotation. 3. Event release. Invoke the event publishing API (POST) in EventBus. Publish events. 4. Subscriber response.
Case 3.
Maven references the corresponding Jar package EventBus
/ / API encapsulation
public class MyEventBus {
/** Event task bus */
private final static EventBus tiemEventBus = new EventBus();
/** * Triggers the synchronization event **@param event
*/
public static void post(Object event) {
tiemEventBus.post(event);
}
/** * Register event handler **@param handler
*/
public static void register(Object handler) {
tiemEventBus.register(handler);
}
/** * Unregister event handler **@param handler
*/
public static void unregister(Object handler) { tiemEventBus.unregister(handler); }}Copy the code
Message Entity Class
public class Message {
private MessageType messageType;
private String messageContent;
public Message(MessageType messageType, String messageContent) {
this.messageType = messageType;
this.messageContent = messageContent;
}
public MessageType getMessageType(a) {
return messageType;
}
public void setMessageType(MessageType messageType) {
this.messageType = messageType;
}
public String getMessageContent(a) {
return messageContent;
}
public void setMessageContent(String messageContent) {
this.messageContent = messageContent;
}
public enum MessageType {
OPENDOOR(1."openDoor"),
CLOSEDOOR(2."closeDoor");
private int code;
private String value;
MessageType(int code, String value) {
this.code = code;
this.value = value;
}
public int getCode(a) {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getValue(a) {
return value;
}
public void setValue(String value) {
this.value = value; }}}Copy the code
Event listeners listen to the ApplicationPreparedEvent context to prepare events, that is, register this listener with EventBus when SpringBoot is loaded to this step. By way of abstract encapsulation, subsequent subclasses implement the subscriber’s eventBus registration by implementing this class.
@Component
abstract class MyApplicationListener implements ApplicationListener<ApplicationPreparedEvent> {
/** * ApplicationPreparedEvent context prepares the event *@param applicationPreparedEvent
*/
@Override
public void onApplicationEvent(ApplicationPreparedEvent applicationPreparedEvent) {
ConfigurableApplicationContext applicationContext = applicationPreparedEvent.getApplicationContext();
MyApplicationListener bean = applicationContext.getBean(this.getClass());
System.out.println("regist listener to eventBus...."+bean); MyEventBus.register(bean); }}Copy the code
Subscribers (that is, listeners) inherit to MyApplicationListener.
@Component
public class MyListentenerSubscribe extends MyApplicationListener{
@Subscribe
public void on(Message message){
System.out.println("Subscribe message-> messgeType:+message.getMessageType()+"\ n messageContent:"+message.getMessageContent()); }}Copy the code
The test here is released directly at Controller implementation time because it is a case implementation. In real businesses, events triggered by specific businesses are released through the business layer. I do this by Posting User
@RestController
public class EventPublishCtrl extends LogBase {
@GetMapping("/publish")
public void publishEvent(a) {
log.info("this publish method...");
MyEventBus.post(new Message(Message.MessageType.OPENDOOR,"Open sesame!)); }}Copy the code
Start the output
The 2019-08-22 14:39:15. 811 WARN 73026 – [the main] com.net flix. Discovery. DiscoveryClient: Using default Backup Registry implementation which does not do anything. 2019-08-22 14:39:15.813 INFO 73026 — [main] com.netflix.discovery.DiscoveryClient : Starting heartbeat executor: renew interval is: 73026-30 2019-08-22 14:39:15. 814 INFO [main] C.N.D iscovery. InstanceInfoReplicator: InstanceInfoReplicator onDemand Update Allowed rate per min is 4 2019-08-22 14:39:15.818 INFO 73026 — [main] com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1566455955817 with initial instances count: 0 14:39:15 2019-08-22. 73026-820 the INFO [main] O.S.C.N.E.S.E urekaServiceRegistry: Registering application UNKNOWN with status UP 2019-08-22 14:39:15.820 INFO 73026 — [main] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1566455955820, current=UP, Previous = STARTING] 14:39:15 2019-08-22. 73026-822 the INFO [nfoReplicator – 0] com.net flix. Discovery. DiscoveryClient: DiscoveryClient_UNKNOWN/kafka1:9090: registering service… regist listener to eventBus…. Com. Uniubi. Springcloud. Practice. The eventBus. MyListentenerSubscribe @ 329 a1f8d 14:39:15 2019-08-22. 73026-914 the INFO [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 9090 (HTTP) with the context path ’14:39:15 2019-08-22. 73026-915 the INFO [main] S.C.N.E.S.E urekaAutoServiceRegistration : Updating the port to 9090 14:39:15 2019-08-22. 73026-917 the INFO [main] C.U.S.P ractice. PracticeApplication: Started PracticeApplication in 4.101 seconds (JVM running for 4.895 [-192.168.63.121] O.A.C.C.C. [Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet ‘DispatcherServlet’
The project starts loading and registers the corresponding listener into eventBus. Test event release
2019- 08 -22 14:43:44.399 INFO 73026 --- [nio-9090-exec-1] c.u.springcloud.practice.common.LogBase : thispublish method... Subscribe message-> messgeType: OPENDOOR messageContent: Open Sesame!Copy the code
The subscriber receives the specific message type, as well as the message content. conclusion
Much of the underlying implementation of springBoot is based on an event-based publish-and-subscribe model. In our daily development process, business decoupling and asynchronous message transmission are achieved. Both can be implemented by implementing a publish and subscribe pattern. This is also the implementation of event-driven decoupling of the core business in the project.
- The pictures in this article are from the Internet. In case of infringement, contact the author.