One, foreword

Yesterday I wrote my first article on the basics of Netty, and for those of you who have read this article, I wrote this ** placeholder ** when I wrote about event-driven

Today, I took advantage of working overtime to quietly learn event-driven content. As I am engaged in finance, I am very busy every day. Only in the evening can I spare a little time for study.

What is event driven?

Baidu’s explanation

The basic structure of an event driver consists of an event collector, an event sender and an event handler. The event collector is dedicated to collecting all events from the user (such as mouse, keyboard events, etc.), from hardware (such as clock events, etc.), and from software (such as the operating system, the application itself, etc.). The event sender is responsible for distributing the events collected by the collector to the target object. Event handlers do the specific event response work

According to Baidu’s explanation, I think the event driving is mainly divided into the following contents:

  • Event source: An object responsible for generating events, such as a Button. Clicking on a Button causes the event to be clicked
  • Event collectors, or event objects, are the information Bridges between event sources and event listeners and are the driving core of the entire event model
  • Event listener (event handler) : The object responsible for handling events

Here’s an example: since I started in finance, I’ll use banks as an example

  • Event collector: calling machine
  • Event source: caller
  • Event listener: customer

Morning after morning session open and customer came to your turn device take number, and event listener is registered to the event) in the collector, teller machine (events), click on your cueing machine began to call * * “please customers to 5, 001 counter business” * *, at this time of the teller and customer for binding (i.e., event sources and event listeners binding)

3. Simple examples

Implementation approach

  • First, you need to implement the event listener, the event collector, and register the event listener with the event collector
  • The event sender sends an event to the event center, which finds and processes the listener for the event
Event sender -----(2)-----> Event collector <--------(1)----- Event listenerCopy the code

3.1 Implementing the event collector

explain

  • 1.ConcurrentHashMap is used to store the binding relationship between the event source and the event listener
private finalConcurrentHashMap<Class<? >, List<EventListener>> subscribers =new ConcurrentHashMap<>();
Copy the code

The first argument is the Class object of the data source, and the second is the listener

  • 2.Executor
Flexible and powerful asynchronous execution framework, which supports a variety of different types of task execution strategy, provides a standard method of decoupling tasks submission process and execution process development, based on producers - consumer model, its submit task thread is equivalent to producers, perform a task thread is equivalent to the consumer, and represented a Runnable task,Copy the code
  • 3.EventCenter

Constructor to instantiate an Executor object

public EventCenter(Executor executor) {
    this.executor = executor;
}
Copy the code
  • 4.registry

The first parameter is the Class object of the event source, and the second is the object of the listener

/** * Bind the event to the event listener@param clazz
 * @param eventListener
 */
public void registry(Class clazz,EventListener eventListener){
    // Run the ConcurrentHashMap command to check whether the listener is registered
    List<EventListener> eventListeners = subscribers.get(clazz);
    // If the listener is not registered, initialize the List
    if(eventListener == null){
        eventListeners = new ArrayList<>();
    }
    // Add listeners to the List
    eventListeners.add(eventListener);
    // Event and event listener binding
    subscribers.put(clazz,eventListeners);
}
Copy the code
  • 5.send

It is used for publishing events, where BanderEvent requires a custom implementation, which we will explain later

/** * Event send *@param bankerEvent
 */
public void send(BankerEvent bankerEvent) throws EventException {
    // Check whether the listener is registered
    List<EventListener> eventListeners = subscribers.get(bankerEvent.getClass());
    if(eventListeners == null || eventListeners.size() == 0) {// Throw an exception if it is not registered
        throw new EventException((short) 500."Event listener not registered");
    }
    // Loop through the listener and publish the event
    for(EventListener eventListener : eventListeners){ executor.execute(()->eventListener.trigger(bankerEvent)); }}Copy the code

Complete structure

** * Event collector/Registry */public class EventCenter {

    /** * is used to bind events to event listeners */
    private finalConcurrentHashMap<Class<? >, List<EventListener>> subscribers =new ConcurrentHashMap<>();

   // Task processing
    private final Executor executor;

    public EventCenter(Executor executor) {
        this.executor = executor;
    }

    /** * Bind the event to the event listener@param clazz
     * @param eventListener
     */
    public void registry(Class clazz,EventListener eventListener){
        // Run the ConcurrentHashMap command to check whether the listener is registered
        List<EventListener> eventListeners = subscribers.get(clazz);
        // If the listener is not registered, initialize the List
        if(eventListener == null){
            eventListeners = new ArrayList<>();
        }
        // Add listeners to the List
        eventListeners.add(eventListener);
        // Event and event listener binding
        subscribers.put(clazz,eventListeners);
    }

    /** * Event send *@param bankerEvent
     */
    public void send(BankerEvent bankerEvent) throws EventException {
        // Check whether the listener is registered
        List<EventListener> eventListeners = subscribers.get(bankerEvent.getClass());
        if(eventListeners == null || eventListeners.size() == 0) {// Throw an exception if it is not registered
            throw new EventException((short) 500."Event listener not registered");
        }
        // Loop through the listener and publish the event
        for(EventListener eventListener : eventListeners){ executor.execute(()->eventListener.trigger(bankerEvent)); }}}Copy the code

3.2 Implementing event listeners

explain

  • ConsumerListener mainly implements the EventListener interface
  • 2. The trigger method is called when the event is triggered
/** * Response to event trigger *@param bankerEvent
 */
@Override
public void trigger(BankerEvent bankerEvent) {
    Integer number = bankerEvent.getNumber();
    log.info("Please go to window 5 for customer {}",number);
}
Copy the code
  • 3. The Registry method is used to register and bind events and event listeners to the registry
@Autowired
private EventCenter eventCenter;

/** * Registering with the event collection center is also equivalent to identifying events to be subscribed to */
@PostConstruct
public void registry(a){
    eventCenter.registry(BankerCreateEvent.class,this);
}
Copy the code

To define an event listener, we first need to define an interface

/** * Event listener interface */
public interface EventListener {
    * is called when the event is triggered@param bankerEvent
     */
    public void trigger(BankerEvent bankerEvent);
}
Copy the code

Specific operation

Implement the class and register with EvnetCenter

/** * Client listener */
@Component
@Slf4j
public class ConsumerListener implements EventListener {

    @Autowired
    private EventCenter eventCenter;

    /** * Registering with the event collection center is also equivalent to identifying events to be subscribed to */
    @PostConstruct
    public void registry(a){
        eventCenter.registry(BankerCreateEvent.class,this);
    }

    /** * Response to event trigger *@param bankerEvent
     */
    @Override
    public void trigger(BankerEvent bankerEvent) {
        Integer number = bankerEvent.getNumber();
        log.info("Please go to window 5 for customer {}",number); }}Copy the code

3.3 Implementing the event source

Create the interface

/** * Teller incident */
public interface BankerEvent {
    public Integer getNumber(a);
}
Copy the code

The implementation class

public class BankerCreateEvent implements BankerEvent {
    Integer number = 100;

    @Override
    public Integer getNumber(a) {
        returnnumber; }}Copy the code

3.4 Implement event publishers

@Component
public class EventSender {
    @Autowired
    private EventCenter eventCenter;

    public void send(BankerEvent bankerEvent){
        // Send the eventeventCenter.send(bankerEvent); }}Copy the code

3.5 Event Registry configuration class

@Configuration
public class EventCenterConfig {

    @Bean
    public EventCenter eventCenter(a){
        ThreadFactory namedThreadFactory = Executors.defaultThreadFactory();
        int corePoolSize = Runtime.getRuntime().availableProcessors();
        int maximumPoolSize = corePoolSize * 2;
        Create a thread pool
        Executor pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 10L,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024),
                namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
        return newEventCenter(pool); }}Copy the code

3.6 Event Invocation

@Slf4j
@SpringBootApplication
public class LinkedApplication {

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext applicationContext = SpringApplication.run(LinkedApplication.class, args);
        // Get the EventSender context
        EventSender eventSender = applicationContext.getBean(EventSender.class);
        while(true) {long orderId = ThreadLocalRandom.current().nextLong();
            // Send the event
            eventSender.send(new BankerCreateEvent());
            Thread.sleep(ThreadLocalRandom.current().nextLong(1000.10000)); }}}Copy the code

The 2020-12-24 00:55:22. 5315-335 the INFO [] – thread pool – 1-1 C.Y.L inked. Listener. ConsumerListener: please customers at counter number 5, 100

Making the address

Github.com/13150702172…

Let’s call it a day. Because I have to go back to work tomorrow. Good night! 🌛