1. Introduction

Some logic in Java development goes something like this: after operation A, proceed to operation B, proceed to operation C. That’s a little unclear. For example, you have dinner, inform your wife (girlfriend) to collect the dishes, and then inform your online friends that you are back and ready to hack. It doesn’t matter if your wife (girlfriend) comes to clean up, you told her. As for your brothers, you can also tell them that they don’t have to set you up, in case they are playing with a three-man carry.

2. The concept of events

Eating dinner is a so-called event. Trigger the next two operations, and they only have a causal relationship. But they do not interfere with each other. A complete event consists of event source, event release, and event listener. Let’s talk about events in Spring.

3. Spring events

The Spring framework uses a number of event mechanisms, such as Spring Boot. Let’s create a new Spring Boot project for convenience. Then follow me step by step through the operation of the event.

3.1 Declaration Event

  • Declare an event. Through inheritanceorg.springframework.context.ApplicationEventTo write events. Time to define the event push to listener need to execute method, of course, can also write trigger logic in the listener. Let’s be clear:
package cn.felord.boot.event;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

/** ** dinner event **@author dax
 * @since8 21:54 2019/7 / * /
@Slf4j
public class EatEvent extends ApplicationEvent {
    private Boolean eatFinished;


    /**
     * Instantiates a new Eat event.
     *
     * @paramEatFinished Whether the meal is complete signals here can also pass other resources */
    public EatEvent(Boolean eatFinished) {
        super(eatFinished);
        this.eatFinished = eatFinished;
    }

    /** * the corresponding listener {@linkApplicationListener<EatEvent>} execute * * to ask your girlfriend to clean up. */
    public void callGirlFriend(a) {
        log.info("Honey! I'm done eating. Let's clean up.");
    }

    /** * the corresponding listener {@linkApplicationListener<EatEvent>} executes the * call brother to open the black. */
    public void callBrothers(a) {
        log.info("Brothers! I'm done eating. Get me black.");
    }

    /** * Dinner signal. **@return the boolean
     */
    public Boolean isEatFinished(a) {
        return this.eatFinished; }}Copy the code

3.2 Event Publishing

Publish event by implementing event publishing interface org. Springframework. Context. ApplicationEventPublisher or its facade interface Org. Springframework. Context. ApplicationEventPublisherAware, recommend a facade interface, which methods to define a active push events below refreshEvent method, The actual agent ApplicationEventPublisher perform its publishEvent methods:

package cn.felord.boot.event;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

/** * Publish events by implementing the event publish interface {@linkApplicationEventPublisher} * or through a facade interface {@linkApplicationEventPublisherAware} * recommended according to the following implementation approach, and the need to register for spring bean * *@author dax
 * @since 2019 /7/8 22:04
 */
@Slf4j
public class EatEventPublisherAware implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher applicationEventPublisher;

    private ApplicationEvent eatEvent;

    public EatEventPublisherAware(ApplicationEvent eatEvent) {
        this.eatEvent = eatEvent;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    /** * The action of the event requires the active trigger to call this method for the event trigger * proxy {@link ApplicationEventPublisher#publishEvent(ApplicationEvent)}
     */
    public void refreshEvent(a) {
        log.info("Sending event...");
        this.applicationEventPublisher.publishEvent(eatEvent); }}Copy the code

3.3 Event Listening

Event listeners are used to listen for events to trigger the associated logic. By implementing org. Springframework. Context. The ApplicationListener < E extends ApplicationEvent > to implement event listener. Pay special attention to the generic type E, which can accept any event if no event is specified, as single responsibility as possible.

package cn.felord.boot.event;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;

/ * * * {@linkEatEvent} Specifies the event listener * for the event@author dax
 * @since2019/7/8 [* /
@Slf4j
public class EatEventListener implements ApplicationListener<EatEvent> {
    @Override
    public void onApplicationEvent(EatEvent eatEvent) {
        // If dinner is over
        if (eatEvent.isEatFinished()) {
            eatEvent.callGirlFriend();
            log.error("Growl from a tigress: Fuck off.");
            eatEvent.callBrothers();
            log.error("It's too late. We're full. Take you tomorrow.");
            log.info("Why don't you follow the code farmer and learn something new?"); }}}Copy the code

3.4 Injecting Spring IoC

Injecting the above three classes into the Spring container, where we use the JavaConfig approach, makes it more obvious.

package cn.felord.boot.config;

import cn.felord.boot.event.EatEvent;
import cn.felord.boot.event.EatEventListener;
import cn.felord.boot.event.EatEventPublisherAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** * these three must be configured as bean **@author dax
 * @since2019/7/8 22:16 * /
@Configuration
public class EventConfig {

    @Bean
    public ApplicationEvent eatEvent(a) {
        return new EatEvent(true);
    }

    @Bean
    public ApplicationListener eatEventListener(a) {
        return new EatEventListener();
    }

    @Bean
    public ApplicationEventPublisherAware eatEventPublisherAware(ApplicationEvent eatEvent) {
        return newEatEventPublisherAware(eatEvent); }}Copy the code

4. Test

The event listener will automatically respond to the event when it listens to it. Let’s write a unit test.

package cn.felord.boot;

import cn.felord.boot.event.EatEventPublisherAware;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class EventSpringApplicationTests {
@Resource
private EatEventPublisherAware eatEventPublisherAware;
    @Test
    public void contextLoads(a) { eatEventPublisherAware.refreshEvent(); }}Copy the code

Let me run it. Let me draw it

At this point you should be able to use Spring events, and the resulting code will be much higher. You can also leverage some of your understanding of the Spring framework. There is, of course, a simpler, annotation-based approach that is not explained here. The relevant code is in my code cloud repository

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn