Spring事件监听

1 案例分析
引用 : https://zhuanlan.zhihu.com/p/101128672
1.1假设业务场景

用户下单成功之后,平台需要发送短信通知下单成功

最直观的写法

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

假设过了一个月之后,下单成功之后,还需要通知物流系统发货

于是就需要修改原有代码

public void order(){
  // 下单成功
  System.out.println("下单成功...");
  // 发送短信
  sendSms();
  // 通知车队发货 
  notifyCar();
}

假设又过了几个月,不需要通知物流系统了,那么又需要修改原有代码

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

根据编码的基本原则,开闭原则,这样的代码是合格的

于是根据一种以增量的方式应对变化的需求,在并发较小时可使用Spring的监听机制,在并发较大时,需要使用消息中间件

img

2 Spring监听机制

订单服务

@Service
public class OrderService {

    @Autowired
    private ApplicationContext applicationContext;

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

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

public class OrderSuccessEvent extends ApplicationEvent {


    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("发送短信...");
    }
}

测试输出

下单成功...
发送短信...
main线程结束...

如果后期针对下单成功有新的操作,可以新写一个事件监听类:

/**
 * 物流服务
 */
@Service
public class CarService  implements ApplicationListener<OrderSuccessEvent> {
    @Override
    public void onApplicationEvent(OrderSuccessEvent event) {
        this.dispatch();
    }

    public void dispatch() {
        System.out.println("发车咯...");
    }
}

这就是“以增量的方式应对变化的需求”,而不是去修改已有的代码。假设有B接口调用了C接口,你修改了C接口,那么B接口可能业务结果就错了,此时调用B接口的A接口也可能受到影响,是连锁反应。所以,一般我们都提倡“对扩展开放,对修改关闭”的原则。

注解方式监听
/**
 * 短信服务,监听LendSuccessEvent,但不用实现ApplicationListener
 */
@Service
public class SmsService {

    /**
     * 发送短信 @EventListener指定监听的事件
     */
    @EventListener(LendSuccesssEvent.class)
    public void sendSms() {

        try {
            Thread.sleep(1000L * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("发送短信...");
    }

}

目前为止,方法的执行都是同步的,但是在业务中,只需要返回订单执行业务的逻辑,不需要等待发送短信,通知物流的时间,所以需要将消息发布的执行机制改为异步执行

Spring异步机制

当SimpleApplicationEventMulticaster中的Executor不为null,就会执行异步通知

@Configuration
public class AsyncEventConfig {

    @Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster
                = new SimpleApplicationEventMulticaster();

        eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return eventMulticaster;
    }

}
          = new SimpleApplicationEventMulticaster();

    eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
    return eventMulticaster;
}

}

Spring监听原理 : https://editor.youkuaiyun.com/md?not_checkout=1&articleId=123542755
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值