spring的事件监听机制

1spring的事件监听机制

1.1发短信案例问题分析

假设现在有这么一个业务场景:

用户在京西商城下单成功后,平台要发送短信通知用户下单成功

我们最直观的想法是直接在order()方法中添加发送短信的业务代码:

public void order(){
    
    
  // 下单成功
  System.out.println("下单成功...");
  // 发送短信
  sendSms();
}

咋一看没什么不妥,但是如果我们加上一根时间轴,那么代码就有问题了:

一个月后,京西搞了自建物流体系,用户下单成功后,需要通知物流系统发货

于是你又要打开OrderService修改order()方法:

public void order(){
    
    
  // 下单成功
  System.out.println("下单成功...");
  // 发送短信
  sendSms();
  // 通知车队发货 
  notifyCar();
}
又过了一个月,东哥被抓了,股价暴跌,决定卖掉自己的车队,所以下单后就不用通知车队了

于是你就重新修改OrderService()方法:

public void order(){
    
    
  // 下单成功
  System.out.println("下单成功...");
  // 发送短信
  sendSms();
  // 车队没了,注释掉这行代码 
  // notifyCar();
}

。。。这样反反复复。。。为了解决这个问题,引入spring监听机制:比如我们可以实现当用户注册后,给他发送一封邮件告诉他注册成功的一些信息,比如用户订阅的主题更新了,通知用户注意及时查看等。

1.2观察者模式

观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时 通知多个 “观察” 该对象的其他对象。

拥有一些值得关注的状态的对象通常被称为目标, 由于它要将自身的状态改变通知给其他对象, 我们也将其称为发布者 (publisher)。 所有希望关注发布者状态变化的其他对象被称为订阅者 (subscribers)。

观察者模式建议你为发布者类添加订阅机制, 让每个对象都能订阅或取消订阅发布者事件流。 实际上, 该机制包括 1) 一个用于存储订阅者对象引用的列表成员变量; 2) 几个用于添加或删除该列表中订阅者的公有方法。
在这里插入图片描述
现在, 无论何时发生了重要的发布者事件, 它都要遍历订阅者并调用订阅者对象的特定通知方法。

实际应用中可能会有十几个不同的订阅者类跟踪着同一个发布者类的事件, 你不会希望发布者与所有这些类相耦合的。因此, 所有订阅者都必须实现同样的接口, 发布者仅通过该接口与订阅者交互。 接口中必须声明通知方法及其参数, 这样发布者在发出通知时还能传递一些上下文数据。
在这里插入图片描述
如果你的应用中有多个不同类型的发布者, 且希望订阅者可兼容所有发布者, 那么你甚至可以进一步让所有订阅者遵循同样的接口。 该接口仅需描述几个订阅方法即可。 这样订阅者就能在不与具体发布者类耦合的情况下通过接口观察发布者的状态。

如果你订阅了一份杂志或报纸, 那就不需要再去报摊查询新出版的刊物了。 出版社 (即应用中的 “发布者”) 会在刊物出版后 (甚至提前) 直接将最新一期寄送至你的邮箱中。
出版社负责维护订阅者列表, 了解订阅者对哪些刊物感兴趣。 当订阅者希望出版社停止寄送新一期的杂志时, 他们可随时从该列表中退出。

在这里插入图片描述
发布者 (Publisher) 会向其他对象发送值得关注的事件。 事件会在发布者自身状态改变或执行特定行为后发生。 发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅构架。

当新事件发生时, 发布者会遍历订阅列表并调用每个订阅者对象的通知方法。 该方法是在订阅者接口中声明的。

订阅者 (Subscriber) 接口声明了通知接口。 在绝大多数情况下, 该接口仅包含一个 update更新方法。 该方法可以拥有多个参数, 使发布者能在更新时传递事件的详细信息。

具体订阅者 (Concrete Subscribers) 可以执行一些操作来回应发布者的通知。 所有具体订阅者类都实现了同样的接口, 因此发布者不需要与具体类相耦合。

订阅者通常需要一些上下文信息来正确地处理更新。 因此, 发布者通常会将一些上下文数据作为通知方法的参数进行传递。 发布者也可将自身作为参数进行传递, 使订阅者直接获取所需的数据。

客户端 (Client) 会分别创建发布者和订阅者对象, 然后为订阅者注册发布者更新。

public interface Rate {
    
    
    /**
     * 增加观察者方法
     * @param company
     */
    public void add(Company company);

    /**
     * 删除观察者方法
     * @param company
     */
    public void remove(Company company);

    /**
     * 汇率改变-主业务逻辑
     * @param number
     */
    public void change(int number);
}
public class RMBRate implements Rate{
    
    
    List<Company> companies = new ArrayList<>();
    @Override
    public void add(Company company) {
    
    
        companies.add(company);
    }

    @Override
    public void remove(Company company) {
    
    
        companies.remove(company);
    }

    @Override
    public void change(int number) {
    
    
        for (Company company : companies) {
    
    
            company.update();
        }
    }
}
public interface Company {
    
    
    /**
     * 订阅者接口-更新操作
     */
    void update();
}
public class ImportCompany implements Company{
    
    
    @Override
    public void update() {
    
    
        System.out.println("ImportCompany的update()");
    }
}
public class ExportCompany implements Company{
    
    
    @Override
    public void update() {
    
    
        System.out.println("ExportCompany的update()");
    }
}
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Rate rate = new RMBRate();
        Company importCompany = new ImportCompany();
        ExportCompany exportCompany = new ExportCompany();
        rate.add(importCompany);
        rate.add(exportCompany);
        rate.change(100);
    }
}

1.3利用Spring事件机制完成需求

OrderService.java订单服务

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

    @Autowired
    private ApplicationContext applicationContext;

    public void order() {
    
    
        // 下单成功
        System.out.println("下单成功...");
        // 发布通知
        applicationContext.publishEvent(new OrderSuccessEvent(this));
        System.out.println("main线程结束...");
    }
}

OrderSuccessEvent.java(继承ApplicationEvent,自定义事件)

public class OrderSuccessEvent extends ApplicationEvent {
    
    

    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public OrderSuccessEvent(Object source) {
    
    
        super(source);
    }
}

SmsService(实现ApplicationListener,监听OrderSuccessEvent)

/**
 * 短信服务,监听OrderSuccessEvent
 */
@Service
public class SmsService implements ApplicationListener<OrderSuccessEvent> {
    
    

    @Override
    public void onApplicationEvent(OrderSuccessEvent event) {
    
    
        this.sendSms();
    }

    /**
     * 发送短信
     */
    public void sendSms() 
        System.out.println("发送短信...");
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
    
    

    @Autowired
    private OrderService orderService;

    @Test
    public void testSpringEvent() {
    
    
        orderService.order();
    }
}

猜你喜欢

转载自blog.csdn.net/zs18753479279/article/details/119800195