Spring boot application event tutorial - reflecting

Jiedao jdon 2021-05-04 12:35:47
spring boot application event tutorial


If you want to “ monitor ” event , We can write... At the source of the event “ Monitor ” To listen for events , But it tightly couples the event source with the logic of the listener . We can dynamically register and unregister listeners for certain events as needed . For the same event , We can also have multiple listeners . This tutorial provides an overview of how to publish and listen to custom events , And explained Spring Boot Built in events .

Events and direct method calls

Events and direct method calls are suitable for different situations . For method calls , It's like an assertion , Regardless of the status of the sending and receiving modules , They all need to know what happened .

On the other hand , For events , We're just saying that an event happened , And inform which modules are not our concern . When we want to pass processing to another thread , It's best to use events ( for example : Send e-mail on completion of certain tasks ). Again , Events are very useful for Test Driven Development .

Events are used to exchange information between loosely coupled components . Because there is no direct coupling between publishers and subscribers , So we can modify the subscriber without affecting the publisher , vice versa . Let's see how Spring Boot Created in the application , Publish and listen to custom events .

1.  Create a  ApplicationEvent

We can use Spring Framework Event publishing mechanism to publish application events .

Let's create a UserCreatedEvent Custom events called by extension ApplicationEvent:

class UserCreatedEvent extends ApplicationEvent {
  private String name;
  UserCreatedEvent(Object source, String name) {
    super(source);
    this.name = name;
  }
  ...
}

source Objects are parameters that can be initialized and passed when an event occurs , Transmission path super() Method .

from Spring 4.2 Start , We can also publish objects directly as events , And there's no need to expand ApplicationEvent:

class UserRemovedEvent {
  private String name;
  UserRemovedEvent(String name) {
    this.name = name;
  }
  ...
}

2. Publish a  ApplicationEvent

We use ApplicationEventPublisher Interface to publish Events :

@Component
class Publisher {
  
  private final ApplicationEventPublisher publisher;
    
    Publisher(ApplicationEventPublisher publisher) {
      this.publisher = publisher;
    }
  void publishEvent(final String name) {
    // Publishing event created by extending ApplicationEvent
    publisher.publishEvent(new UserCreatedEvent(this, name));
    // Publishing an object as an event
    publisher.publishEvent(new UserRemovedEvent(name));
  }
}

When the object we publish is not ApplicationEvent when ,Spring Will use automatically PayloadApplicationEvent Pack it

3. Monitoring events

Now we know how to create and publish custom events , Let's see how to listen to events . An event can have multiple listeners that perform different tasks according to the requirements of the application .

There are two ways to define listeners . We can use @EventListener Comments or implementations ApplicationListener Interface . In either case , The listener class must be Spring management .

from Spring 4.1 Start , Now you can simply annotate hosting bean Methods ,@EventListener To automatically register ApplicationListener The method that matches the signature of the method :

@Component
class UserRemovedListener {
  @EventListener
  ReturnedEvent handleUserRemovedEvent(UserRemovedEvent event) {
    // handle UserRemovedEvent ...
    return new ReturnedEvent();
  }
  @EventListener
  void handleReturnedEvent(ReturnedEvent event) {
        // handle ReturnedEvent ...
  }
  ...
}

When enabling annotation driven configuration , No other configuration required . Our method can listen to multiple events , Or if we want to define it without any parameters at all , Then the event type can also be specified on the annotation itself . Example :@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class}).

For those with comments @EventListener The return type of the method is defined as not void,Spring The results will be released to us as new events . In the example above ,ReturnedEvent The results returned by the first method will be published , And then it's dealt with in the second way .

If specified SpEL,Spring Only in some cases is it allowed to trigger our listener condition:

@Component
class UserRemovedListener {
  @EventListener(condition = "#event.name eq 'reflectoring'")
  void handleConditionalListener(UserRemovedEvent event) {
    // handle UserRemovedEvent
  }
}

Only if the expression evaluates to true, Or contains one of the following strings :“true”, “on”, “yes”, or “1”. Method parameters are exposed by their names . The conditional expression also exposes a reference to raw ApplicationEvent(#root.event) And the actual method parameters “ root ” Variable (#root.args)

In the example above ,UserRemovedEvent Only when the #event.name The value of is 'reflectoring', Will trigger the listener .

Another way to listen for events is to implement ApplicationListener Interface :

@Component
class UserCreatedListener implements ApplicationListener<UserCreatedEvent> {
  @Override
  public void onApplicationEvent(UserCreatedEvent event) {
    // handle UserCreatedEvent
  }
}

As long as the listener object is in Spring Register in the context of the application , It will receive events . When Spring When routing an event , It uses the signature of the listener to determine if it matches the event .

Asynchronous event listener

By default ,spring Events are synchronized , This means that the publisher thread will block , Until all listeners have finished processing the event .

To make the event listener run in asynchronous mode , So here's what we're going to do @Async Use comments on this listener :

@Component
class AsyncListener {
  @Async
  @EventListener
  void handleAsyncEvent(String event) {
    // handle event
  }
}

In order to make @Async The notes take effect , We have to annotate one more @Configuration class , Use @EnableAsync notes SpringBootApplication class .

The code example above also shows , We can String As an event . Use at your own risk . It's best to use data types specific to our use cases , To avoid conflict with other events .

Transaction binding events

Spring Allows us to bind the event listener to a stage of the current transaction . When the result of the current transaction is important to the listener , This allows events to be used more flexibly .

When we annotate our methods @TransactionalEventListener, We get an extended event listener , The listener knows the transaction :

@Component
class UserRemovedListener {
  @TransactionalEventListener(phase=TransactionPhase.AFTER_COMPLETION)
  void handleAfterUserRemoved(UserRemovedEvent event) {
    // handle UserRemovedEvent
  }
}

UserRemovedListener  Called only when the current transaction is complete .

We can bind listeners to the following stages of a transaction :

  • AFTER_COMMIT: After the transaction is successfully committed , The event will be handled . If the event listener runs only if the current transaction is successful , You can use this method .
  • AFTER_COMPLETION: This event is handled when the transaction is committed or rolled back . for example , We can use it to perform cleanup after the transaction is completed .
  • AFTER_ROLLBACK: After the transaction is rolled back , The event will be handled .
  • BEFORE_COMMIT: The event will be processed before the transaction is committed . for example , We can use it to make transactional O / R The mapping session refreshes to the database .

Spring Boot Application events for

Above is Spring event ,Spring Boot Provides several predefined ApplicationEvent Of , These predefined bindings are bound to SpringApplication Life cycle .

stay ApplicationContext Some events are triggered before creation , So we can't register these events as @Bean. We can register listeners for these events by manually adding listeners :

@SpringBootApplication
public class EventsDemoApplication {
  public static void main(String[] args) {
    SpringApplication springApplication = 
        new SpringApplication(EventsDemoApplication.class);
    springApplication.addListeners(new SpringBuiltInEventsListener());
    springApplication.run(args);
  }
}

By way of META-INF/spring.factories File added to our project , We can also register listeners , No matter how you create the app . And through the following org.springframework.context.ApplicationListener Key reference listener :

org.springframework.context.ApplicationListener= com.reflectoring.eventdemo.SpringBuiltInEventsListener

class SpringBuiltInEventsListener 
    implements ApplicationListener<SpringApplicationEvent>{
  @Override
  public void onApplicationEvent(SpringApplicationEvent event) {
    // handle event
  }
}

Once you make sure the event listener is properly registered , We can monitor all of the Spring Boot Of SpringApplicationEvents. Let's look at them in the order in which they are executed during application startup :

ApplicationStartingEvent

ApplicationStartingEvent At the start of the run, but before any processing , In addition to the registration of listeners and initializers .

ApplicationEnvironmentPreparedEvent

When Environment Available in context , One ApplicationEnvironmentPreparedEvent Be triggered , Because of this time Environment Will be ready , So we can do something else bean Check and modify it before using it .

ApplicationContextInitializedEvent

ApplicationContext When you're ready , One ApplicationContextInitializedEvent Trigger ,ApplicationContextInitializers Called not yet loaded bean Definition . stay bean Initialize to Spring Before the container , We can use it to perform tasks .

ApplicationPreparedEvent

When ApllicationContext When ready , One ApplicationPreparedEvent Will trigger , But it won't refresh .

At the ready Environment and bean The definition will be loaded .

ContextRefreshedEvent

When ApplicationContext On refresh ,ContextRefreshedEvent Will trigger .

ContextRefreshedEvent It's directly from Spring, instead of Spring Boot, Does not inherit extensions SpringApplicationEvent.

WebServerInitializedEvent

If we use Web The server ,WebServerInitializedEvent It's in Web When the server is ready, it triggers a.ServletWebServerInitializedEvent and ReactiveWebServerInitializedEvent Namely servlet And reactive variables .

WebServerInitializedEvent Not inheritance extension SpringApplicationEvent.

ApplicationStartedEvent

After the context has been refreshed , One ApplicationStartedEvent Trigger , But in any Spring boot Before both the application and the command line run are called .

ApplicationReadyEvent

One ApplicationReadyEvent When triggered, the application is ready for a service request .

It is recommended not to modify the internal state at this time , Because all initialization steps will be completed .

ApplicationFailedEvent

One ApplicationFailedEvent If there is any abnormality , Application failed to start ignition . This can happen at any time during startup . We can use it to perform some tasks , For example, execute a script or issue a notification when a startup fails .

Conclusion

Events are designed to be in the same application context in Spring bean Simple communication between . from Spring 4.2 Start , The infrastructure has been significantly improved , It also provides the annotation based model and the function of publishing any event .

You can stay GitHub On Find the sample code .

版权声明
本文为[Jiedao jdon]所创,转载请带上原文链接,感谢
https://javamana.com/2021/05/20210504123223589L.html

  1. Spring 3中异步方法调用
  2. AOP相关讨论
  3. jf能支持的表现层目前只有struts 1.x么?
  4. 在j2ee中实现一般java对象数据库的方法。
  5. FTP connecting windows and Linux
  6. Decorator design pattern - gene zeiniss
  7. Asynchronous method call in spring 3
  8. Discussion on AOP
  9. Is struts 1. X the only presentation layer supported by JF?
  10. The method of realizing general Java object database in J2EE.
  11. PDF转HTML工具——用springboot包装pdf2htmlEX命令行工具
  12. Pdf to HTML tool -- Wrapping pdf2htmlex command line tool with springboot
  13. MySQL 的 in 查询不走索引?我拿什么拯救你!
  14. MySQL in query does not go index? What can I do to save you!
  15. PDF转HTML工具——用springboot包装pdf2htmlEX命令行工具
  16. Pdf to HTML tool -- Wrapping pdf2htmlex command line tool with springboot
  17. Java小白入门必学!最全数据类型和运算符笔记,附实例
  18. Java Xiaobai introduction must learn! Notes on the most complete data types and operators, with examples
  19. Spring MVC请求与响应
  20. Spring MVC request and response
  21. Java 11已经不再完全免费,不要陷入Oracle的Java 11陷阱
  22. Vue.js比jQuery更容易学习
  23. 启动/删除Docker容器时出现问题 - 如何修复
  24. eclipse run on server时出现了错误信息.求急!!
  25. 请教高手一个关于lunce的问题:java.io.IOException: Cannot rename ...\segments.new
  26. Java 11 is no longer completely free. Don't fall into the Java 11 trap of Oracle
  27. Vue. JS is easier to learn than jQuery
  28. Problem starting / deleting docker container - how to fix it
  29. There is an error message in eclipse run on server!!
  30. Ask a question about lunce: java.io.ioexception: cannot rename... \ segments.new
  31. 从零搭建Spring Boot脚手架(2):集成mybatis
  32. 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper
  33. 只知道java反射,宁知道内省吗?
  34. Build spring boot scaffold from scratch (2): integrate mybatis
  35. Build spring boot scaffold from scratch (4): handwritten mybatis general mapper
  36. Do you prefer introspection to reflection?
  37. ASP调用SDK微信分享好友、朋友圈
  38. ASP calls SDK wechat to share friends and circle of friends
  39. BAT 必问的 MySQL 面试题你都会吗?
  40. Do you know all the MySQL interview questions that bat must ask?
  41. ASP调用SDK微信分享好友、朋友圈
  42. ASP calls SDK wechat to share friends and circle of friends
  43. SpringCloud(六)Bus消息总线
  44. 详解JavaScript中的正则表达式
  45. Springcloud (6) bus message bus
  46. Explain regular expressions in JavaScript
  47. Java 响应式关系数据库连接了解一下
  48. Java14它真的来了, 真是尾气都吃不到了
  49. 视频:使用Docker搭建RabbitMQ环境
  50. Java responsive relational database connection
  51. Java14 it's really coming. I can't eat the exhaust
  52. Video: building rabbitmq environment with docker
  53. SpringCloud(六)Bus消息总线
  54. 详解JavaScript中的正则表达式
  55. Springcloud (6) bus message bus
  56. Explain regular expressions in JavaScript
  57. Docker实战:用docker-compose搭建Laravel开发环境
  58. Docker: building laravel development environment with docker compose
  59. 求助,JAVA如何获取系统当前所有进程
  60. 有人用过JMeter或用HttpUnit写过测试吗????