What is ApplicationEventPublisher?
As implementation of Observer pattern, provide interface for event programming.
1. Make Event Event Publisher consist of occur part and receive part and Object to be used for delivery.
First, occur part.
To occur EventPublisher, should use ApplicationEventPublisher object, ApplicationContext has ApplicationEventPublisher object already.
And use publichEvent method with Object to be used for delivery inside.
1 2 3 4 5 6 7 8 9 10 11 @Component public class EventRunner implements ApplicationRunner { @Autowired ApplicationEventPublisher eventPublisher; @Override public void run (ApplicationArguments args) throws Exception { eventPublisher.publishEvent(new MyEvent(this , 100 )); } }
Second, The Object to be used for delivery like below code.
In constructor, meaning of source is for can tracking what object occurred.
1 2 3 4 5 6 7 8 9 10 11 12 public class MyEvent { private int data; public MyEvent (Object source, int data) { this .data = data; } public int getData () { return data; } }
Third, receive part like below code.
Need to write @Component for register bean and a @EventListener on the method want to receive.
1 2 3 4 5 6 7 8 @Component public class MyEventHandler { @EventListener public void onApplicationEvent (MyEvent myEvent) { System.out.println("Event occurred -> " + myEvent.getData()); } }
Then the result like below.
2. Handle event If there are over 2 receive handler, what is order?
Create another handler for test.
1 2 3 4 5 6 7 8 @Component public class AnotherHandler { @EventListener public void handle (MyEvent myEvent) { System.out.println("Another -> " +myEvent.getData()); } }
Then result is like below.
1 2 Event occurred -> 100 Another -> 100
If want to give order at each receiver, can write ‘@Order(Ordered.HIGHEST_PRECEDENCE)’.
1 2 3 4 5 6 7 8 9 @Component public class AnotherHandler { @EventListener @Order (Ordered.HIGHEST_PRECEDENCE) public void handle (MyEvent myEvent) { System.out.println("Another -> " +myEvent.getData()); } }
Then the result like below.
1 2 Another -> 100 Event occurred -> 100
When use to thread, need write @Async .
1 2 3 4 5 6 7 8 9 10 @Component public class AnotherHandler { @EventListener @Async public void handle (MyEvent myEvent) { System.out.println("Current Thread -> " + Thread.currentThread().toString()); System.out.println("Another -> " +myEvent.getData()); } }
And need write @EnableAsync in Application.java
1 2 3 4 5 6 7 8 @SpringBootApplication @EnableAsync public class Application { public static void main (String[] args) { SpringApplication.run(Application.class , args ) ; } }
Events provided by spring.
ContextRefreshedEvent : Occurs when create or refresh ApplicationContext.
ContextStartedEvent : Occurs when receive signal to start() ApplicationContext.
ContextStoppedEvent : Occurs when receive signal to stop() ApplicationContext.
ContextClosedEvent : Occurs when remove singleton bean to close() ApplicationContext.
RequestHandledEvent : Occurs when request HTTP.
Code structure like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Component public class EventRunner implements ApplicationRunner { @Autowired ApplicationEventPublisher eventPublisher; @Override public void run (ApplicationArguments args) throws Exception { eventPublisher.publishEvent(new MyEvent(this , 100 )); ((ConfigurableApplicationContext)eventPublisher).start(); ((ConfigurableApplicationContext)eventPublisher).stop(); ((ConfigurableApplicationContext)eventPublisher).close(); } }
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 @Component public class AnotherHandler { @EventListener @Async public void handle (MyEvent myEvent) { System.out.println("Current Thread -> " + Thread.currentThread().toString()); System.out.println("Another -> " +myEvent.getData()); } @EventListener public void handle (ContextRefreshedEvent event) { System.out.println("Refresh" ); } @EventListener public void handle (ContextStartedEvent event) { System.out.println("Start" ); } @EventListener public void handle (ContextStoppedEvent event) { System.out.println("Stop" ); } @EventListener public void handle (ContextClosedEvent event) { System.out.println("Close" ); } }
The result like this.
1 2 3 4 5 6 7 8 9 10 11 Refresh 2020-02-05 00:07:51.660 INFO 2848 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2020-02-05 00:07:51.663 INFO 2848 --- [ main] com.example.demo.Application : Started Application in 2.354 seconds (JVM running for 3.252) class com.example.demo.eventPublisher.EventRunner Current Thread -> Thread[main,5,main] Event occurred -> 100 Current Thread -> Thread[task-2,5,main] Another -> 100 Start Stop Close