Location>code7788 >text

Springboot Asynchronous Events Configuration and Usage

Popularity:212 ℃/2024-10-23 17:53:32

Spring provides a complete event handling mechanism , the bottom of the built-in implementation of some of the events and listeners , while supporting developers to extend their own implementation of events and listeners .

Generally this event-based implementation in the actual development of the project we mainly used to decouple, and do asynchronous processing (the default is synchronous), to provide the application response speed.

core architecture

First, a brief look at what interface classes need to be involved to implement custom event listeners in Spring, ignoring asynchronous references, annotations, and implementation will be talked about later.

image

Basic realization steps

  1. Custom events: generally inherited from ApplicationEvent can be, pay attention to the inside to define and implement their own event methods, that is, specifically what this event to do, generally in the event class, or based on the event class to achieve can be.
  2. Event Publishing: Inject ApplicationEventPublisher class into the business code, and then call publishEvent method in the specific business method, passing in the above customized event, as well as customized necessary parameters and other information
  3. Implementation of event listener: with the event, also released, there must be a corresponding listener to call the specific event, the general realization of ApplicationListener generic pass their own event type can be

caveat

  1. Exceptions and things: By default, event publishing, listening and processing are all bound to the current business thread, that is, the event task is operated in the same thread. Therefore, whether the event release leads to an exception, or a specific event task implementation method exception, will lead to the current business exception; accordingly, if the current business has things, then the exception will also be rolled back.
  2. event type: first of all, you must customize their own events, and secondly, when listening to listen to their own events, rather than listening to the base class or interface and then go to judgment, so that instead of losing the flexibility of programming based on the event listener, but also illegal to open and close the principle, and is not conducive to the expansion of the later. Specific events can be defined in some other additional parameters, so that it is convenient in the specific method to pass the reference to use
  3. Event order: multiple events can be posted at a time, whether they are the same or different, and the execution order is also in the order of posting by default.

Scenario Applications

Here to order completion and push to the platform order related data for the business model to illustrate the example.Spring4.2 provides annotations to achieve the event listener, very convenient, here we use annotations to achieve the way to listen to it.

  • Abbreviated business class: contains event postings
@Resource
private ApplicationEventPublisher publisher;

public void completeTrade(TradeOrder trade){
  (trade);
  (new TradeStatusEvent(this,new (trade,"Fulfillment of orders")));
}
  • Definition of specific events: inherited from ApplicationEvent
public class TradeStatusEvent extends ApplicationEvent {
    private static final Logger logger = ();

    private Params params;
    
    public Params getParams(){
      return ;
    }
    
    public TradeStatusEvent(Object source,Params param) {
        super(source);
         = param;
    }
    
    public void send(){
      try{
        ("", ().note()..build());
      } catch(Exception e){
        ("TradeStatusEventHandling of exceptions:",e);
      }
    }
    
    
    public static class Params {
        private TradeOrder trade;
        private String note;
        //get、set Defining other parameters, etc.
    }
}
  • Listening implementation: use annotations, note that here I'm using theTransaction listener annotations , according to specific business scenarios can choose specific annotations, such as the most commonly used @EventListener.Because my claim here is that the current thing is submitted after the completion of the push message, and the actual situation is to enable the asynchronous listening to achieve, at the same time, some people in the listening method may also perform a checkback, that is, to query the data submitted in the business, so if this is not labeled here as the thing is submitted to the implementation of the asynchronous case can not get the data
@Component
public class TradeStatusEventListener {

    @TransactionalEventListener(phase= TransactionPhase.AFTER_COMMIT, fallbackExecution=true)
    void handlerAfterComplete(TradeStatusEvent event) {
        ();
    }
}

asynchronous implementation

The so-called asynchronous implementation, generally refers to asynchronous listening, the main business logic and message listening tasks into different threads to execute, to improve the response speed of the business.

Springboot we have more than one way to achieve asynchronous listener execution, the simplest and most direct and asynchronous method to achieve exactly the same, just listen to the method with @Async annotation (provided that asynchronous execution is enabled)

  • First approach: Configuration configuration class with annotations@EnableAsyncto enable Spring's asynchronous method execution capabilities. Then add the listener method to the@Asyncannotation, marked this method is asynchronous execution. over on the line [we did not configure the asynchronous thread right? That is, it will be directly new Thread () to perform asynchronous tasks? Of course not, but Spring provides by default and initialized a thread pool dedicated to the execution of asynchronous tasks ThreadPoolTaskExecutor, will take over all the asynchronous tasks executed in the same thread pool. Also supports customized processing, we will talk about the follow-up]
@Configuration
@EnableAsync
public class AppConfig{}
//````
@Component
public class TradeStatusEventListener {

    @Async
    @TransactionalEventListener(phase= TransactionPhase.AFTER_COMMIT, fallbackExecution=true)
    void handlerAfterComplete(TradeStatusEvent event) {
        ();
    }
}
  • The second approach: If you don't want to globally open the asynchronous, just want to implement asynchronous tasks for the event listener code? That is the simplest is directly listening to where new Thread ().start (), not controlled, not elegant, but the business scenario is simple, the access to the case of small is not impossible. That to standardize it, is to create a thread pool, such as ExecutorService executorService = (); and then where to use (...) Execution can be.
  • The third way: elegant point of implementation, create SimpleApplicationEventMulticaster bean, and then create a thread pool to stuff it, note that you need to inject the custom implementation into the Spring container. Other code do not have to make any changes, just like the synchronization logic, in the event of the release of the broadcast will use multicastEvent call taskExecutor to get a thread to perform the task of listening!
@Configuration
public class AppConfig{
  @Bean
  public SimpleApplicationEventMulticaster simpleApplicationEventMulticaster(){
        SimpleApplicationEventMulticaster mu = new SimpleApplicationEventMulticaster();
        // Here I have created a bounded queue task thread pool for immediate execution using the task constructor provided by spring
        Executor taskExecutor = new TaskExecutorBuilder().corePoolSize(8).maxPoolSize(200).queueCapacity(20).threadNamePrefix("trade-send-"). build();
        (taskExecutor).
        // Set up exception handling
        ((t)->{
            //("========== Failed to call the platform send message method,",t);
        });
    return mu;
  }
}

The Framework Principle

  • Why does asynchronous listening only require @EnableAsync, and @Async on methods?
    • When we use Springboot, the introduction of the starter will automatically introduce spring-boot-autoconfigure, this package implements a lot of autoconfiguration features (the convention is greater than the configuration) name is xxxAutoConfigurationFor example, what we're talking about here is TaskExecutionAutoConfiguration, which loads and creates a default task thread pool when the container is started, which can be configured via the opening attribute. Note that TaskExecutionAutoConfiguration initializes a default thread pool whether or not the @EnableAsync annotation is added, because this is global.
      image

    • The role of @EnableAsync is to tell Spring at container startup that I can support asynchronous processing tasks, you look at it.Spring's good friend, I have a special interceptor for you to mess with.
      image

    • When we add annotations, Spring will follow the configuration will be ready to do all the work, so as to do out-of-the-box, directly to a step.

summarize

  • The four cores of the Spring event model: the event source, also known as the business side, the event, the broadcaster, and the listener.
  • The event mechanism supports synchronous and asynchronous, adjusted and used as needed. When using asynchronous listening , it is recommended to use a thread pool to manage threads , efficient , stable and easy to maintain .
  • When using Springboot by way of annotations to listen, enable asynchronous enjoy the silky smooth. The actual principle at the core is the observer pattern.