Practical application scenarios of SpringBoot ApplicationListener observer pattern

Table of contents

1. Overview of ApplicationListener:

2. What is ApplicationListener?

3. Built-in events:

4. Usage scenarios:

Five, ApplicationListener actual combat case:

5.1 Basic business scenario code construction

5.1.1 Create order service

5.1.2 Calling with controller

5.1.3 Testing

5.2 Iteration of business upgrade

5.3 Optimizing code

5.3.1 Create event

5.3.2 Event Listeners

5.3.3 Event publishing

5.3.4 Testing


1. Overview of ApplicationListener:

接下来我们首先来看看ApplicationListener的基本概念、一些内置的事件以及使用场景。


2. What is ApplicationListener?

ApplicationListener可以监听某个事件的event,触发时机可以穿插在业务方法执行过程中,用户可以自定义某个业务事件。但是spring内部也有一些内置事件,这种事件,可以穿插在启动调用中。我们也可以利用这个特性,来自己做一些内置事件的监听器来达到和前面一些触发点大致相同的事情


3. Built-in events:

Spring also has some built-in events, which can be interspersed in the startup call. We can also use this feature to do some built-in event listeners to achieve roughly the same thing as the previous trigger points.

Next, list the main built-in events of spring:

(1)ContextRefreshedEvent

This event is published when the ApplicationContext is initialized or refreshed. This can also happen using the refresh() method in the ConfigurableApplicationContext interface. The initialization here means: all Beans are successfully loaded, post-processing Beans are detected and activated, all Singleton Beans are pre-instantiated, and the ApplicationContext container is ready for use.

(2)ContextStartedEvent

This event is published when the ApplicationContext is started using the start() method in the ConfigurableApplicationContext (ApplicationContext subinterface) interface. You can poll your database, or you can restart any stopped applications after receiving this event.

(3)ContextStoppedEvent

This event is published when the ApplicationContext is stopped using stop() in the ConfigurableApplicationContext interface. You can do the necessary cleanup after receiving this event

(4)ContextClosedEvent

This event is published when the ApplicationContext is closed using the close() method in the ConfigurableApplicationContext interface. A closed context has reached the end of its lifetime; it cannot be refreshed or restarted

(5)RequestHandledEvent

This is a web-specific event that tells all beans that the HTTP request has been serviced. Can only be applied to web applications using DispatcherServlet. When using Spring as the front-end MVC controller, the system will automatically trigger this event when Spring finishes processing user requests

4. Usage scenarios:

  1. Publish-subscribe/observer model to achieve decoupling between businesses.
  2. For example, adding new users needs to send text messages, record logs, etc. It is not reasonable to pile up these logics at the end of the new method, and it is not easy to reuse.
  3. It is very helpful for decoupling code. For example, notification messages must be inserted after the completion of various business scenarios. After the business logic of each scenario code is completed, a corresponding event is directly released, and the listener can handle the monitoring logic. It is not necessary to add this piece of code for each scene.

Five, ApplicationListener actual combat case:

Business scenario description: After many platform orders are successfully created, a text message will be sent to the business operator to remind them.

For such a business scenario, how do we code under normal circumstances and how to code using ApplicationListener.

5.1 Basic business scenario code construction

First of all, we build a set of basic code structure according to the routine.

5.1.1 Create order service

Build an order service, the main function is to create an order and send a text message.


package com.test.service;

import org.springframework.stereotype.Service;

/**
 * 订单服务
 */
@Service
public class OrderService {

    /**
     * 创建订单.
     */
    public void createOrder(){
        //1. 创建订单: 生成订单信息,然后保存到数据库.
        System.out.println("创建订单 - 生成订单信息,然后保存到数据库");

        //2. 发送短信: 调用短信服务,给手机号发送短信信息.
        System.out.println("发送短信 - 调用短信服务,给手机号发送短信信息");

    }

}

5.1.2 Calling with controller

Write a controller to call the order service for easy testing:

package com.test.controller;

import com.kfit.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 订单的Controller
 */
@RestController
public class OrderController {
    @Autowired
    private OrderService orderService;

    @RequestMapping("/createOrder")
    public  String createOrder(){
        orderService.createOrder();
        return "创建成功!";
    }
}

5.1.3 Testing

Start the application for testing, the access address is as follows:

http://127.0.0.1:8080/createOrder

5.2 Iteration of business upgrade

Existing new requirements: It is necessary to add a function of WeChat notification. The normal practice is to add the code logic of WeChat notification in OrderService, as follows:

package com.test.service;

import org.springframework.stereotype.Service;

/**
 * 订单服务
 */
@Service
public class OrderService {

    /**
     * 创建订单.
     */
    public void createOrder(){
        //1. 创建订单: 生成订单信息,然后保存到数据库.
        System.out.println("创建订单 - 生成订单信息,然后保存到数据库");

        //2. 发送短信: 调用短信服务,给手机号发送短信信息.
        System.out.println("发送短信 - 调用短信服务,给手机号发送短信信息");

        //3. 发送微信 - 调用微信公众号的通知服务,进行发送。
        System.out.println("发送微信 - 调用微信公众号的通知服务,进行发送");
    }

}

There is a problem: every time an order needs to be added with a new function (such as a new notification method), the original class must be modified, which is difficult to maintain and violates the principles of design patterns:

(1) Single responsibility: order saving function, mixed with message notification functions

(2) Open-closed principle: open for expansion, closed for modification

Optimization scheme: use the observer mode to separate the creation of orders and message notifications, and low coupling. You can choose message queue, Spring event mechanism, etc. This article chooses Spring event mechanism.

5.3 Optimizing code

If you use the event mechanism, you need to define the event of the order first, then use the listener to listen to the event, and finally publish the event when the order is created.

5.3.1 Create event

Build the OrderCreateEvent event and inherit the interface ApplicationEvent:

package com.test.service;

import org.springframework.context.ApplicationEvent;

/**
 * 订单创建事件
 */
public class OrderCreateEvent extends ApplicationEvent {

    private String orderInfo;//订单信息
    public OrderCreateEvent(Object source,String orderInfo){
        super(source);
        this.orderInfo = orderInfo;
    }

    public String getOrderInfo() {
        return orderInfo;
    }

    public void setOrderInfo(String orderInfo) {
        this.orderInfo = orderInfo;
    }
}

5.3.2 Event Listeners

Event monitoring, mainly SMS sending monitoring and WeChat sending monitoring.

SmsListener:


package com.test.service;

import com.kfit.order.order.event.OrderCreateEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 *  OrderCreateEvent的短信监听.
 */
@Component
public class SmsListener implements ApplicationListener<OrderCreateEvent> {
    @Override
    public void onApplicationEvent(OrderCreateEvent event) {
        //. 发送短信: 调用短信服务,给手机号发送短信信息.
        System.out.println("发送短信 - 调用短信服务,给手机号发送短信信息;订单信息:"+event.getOrderInfo());
    }
}


WechatListener:


package com.test.service;

import com.kfit.order.order.event.OrderCreateEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 *  WechatListener的微信监听.
 */
@Component
public class WechatListener implements ApplicationListener<OrderCreateEvent> {
    @Override
    public void onApplicationEvent(OrderCreateEvent event) {
        //. 发送微信 - 调用微信公众号的通知服务,进行发送。
        System.out.println("发送微信 - 调用微信公众号的通知服务,进行发送;订单信息:"+event.getOrderInfo());
    }
}

5.3.3 Event publishing

Event publishing can be published using the publishEvent method of ApplicationContext or ApplicationEventPublisher. Modify the code of OrderService:


package com.test.service;

import com.test.service.OrderCreateEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

/**
 * 订单服务
 */
@Service
public class OrderService {
    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 创建订单.
     */
    public void createOrder(){
        //1. 创建订单: 生成订单信息,然后保存到数据库.
        System.out.println("创建订单 - 生成订单信息,然后保存到数据库");


        //2. 发布事件
        OrderCreateEvent orderCreateEvent = new OrderCreateEvent(this,"orderNo:20230815");
        applicationContext.publishEvent(orderCreateEvent);

        //applicationEventPublisher.publishEvent(orderCreateEvent);//也可以
}

5.3.4 Testing

Start the application for testing, the access address is as follows:

http://127.0.0.1:8080/createOrder

If you want to execute the monitoring of sending WeChat first, you can add the @Order annotation to the class. The smaller the value, the more execution, that is, @Order(1) will be executed before @Order(2).

Source code: https://download.csdn.net/download/u011974797/88280036

Original text: springboot ApplicationListener Observer pattern practical application scenarios

Guess you like

Origin blog.csdn.net/u011974797/article/details/132605189