以下伪代码是一个保存订单的功能,并会发送短信消息:
/**
* Author heling on 2019/1/9
*/
@Service
public class OrderServiceImpl implements OrderService {
@Override
public void saveOrder() {
//1.创建订单
System.out.println("订单创建成功");
//2.发送短信
System.out.println("恭喜您订单创建成功!----by sms");
}
}
现有新需求:需要加一个微信通知的功能,代码如下:
/**
* Author heling on 2019/1/9
*/
@Service
public class OrderServiceImpl implements OrderService {
@Override
public void saveOrder() {
//1.创建订单
System.out.println("订单创建成功");
//2.发送短信
System.out.println("恭喜您订单创建成功!----by sms");
//新需求:微信通知
// 3.发送微信
System.out.println("恭喜您订单创建成功!----by wechat");
}
}
存在问题:每次创建订单需要加新功能(如新的通知方式),则要修改原有的类,难以维护。
违背设计模式的原则
1.单一职责:订单保存功能,杂糅了消息通知这些功能
2.开闭原则:对拓展开放,对修改关闭
优化方案:使用观察者模式,使创建订单和消息通知进行分离,低耦合。可以选择消息队列,spring事件机制等,本文选择Spring事件机制。
改造开始:
1.创建事件
package com.pengshu.magicwallet.admin.test;
import org.springframework.context.ApplicationEvent;
import java.util.List;
/**
* Author heling on 2019/1/9
* 订单创建活动事件
*/
public class OrderCreateEvent extends ApplicationEvent {
private String name;
//消息参数
private List contentList;
public OrderCreateEvent(Object source, String name, List contentList) {
super(source);
this.name = name;
this.contentList = contentList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getContentList() {
return contentList;
}
public void setContentList(List contentList) {
this.contentList = contentList;
}
}
2.监听器
package com.pengshu.magicwallet.admin.test;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* Author heling on 2019/1/9
* 短信监听器
* ApplicationListener是无序的
*/
@Component
public class SmsListener implements ApplicationListener {
@Override
public void onApplicationEvent(OrderCreateEvent event) {
//发送短信
System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by sms");
}
}
package com.pengshu.magicwallet.admin.test;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* Author heling on 2019/1/9
* 微信监听器
*/
@Component
public class WechatListener implements ApplicationListener {
@Override
public void onApplicationEvent(OrderCreateEvent event) {
//发送微信
System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by wechat");
}
}
3.事件发布
package com.pengshu.magicwallet.admin.test;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
/**
* Author heling on 2019/1/9
*/
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private ApplicationContext applicationContext;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void saveOrder() {
//1.创建订单
System.out.println("订单创建成功");
//2.发布事件
ArrayList contentList = new ArrayList<>();
contentList.add("heling");
contentList.add("123456789");
OrderCreateEvent orderCreateEvent = new OrderCreateEvent(this, "订单创建", contentList);
applicationContext.publishEvent(orderCreateEvent);//ApplicationContext是我们的事件容器上层,我们发布事件,也可以通过此容器完成发布
//applicationEventPublisher.publishEvent(orderCreateEvent);//也可以
System.out.println("finished!");
}
}
打印结果:
订单创建成功
heling,您的订单:123456789创建成功! ----by sms
heling,您的订单:123456789创建成功! ----by wechat
finished!
如何异步执行监听器?
1.springboot开启事件异步设置
package com.pengshu.magicwallet;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@MapperScan("com.pengshu.magicwallet.mapper")
@PropertySource("classpath:authority.properties")
@EnableTransactionManagement
@EnableAsync //开启spring事件异步设置,加@Async注解
public class MagicWalletAdminApplication {
public static void main(String[] args) {
SpringApplication.run(MagicWalletAdminApplication.class, args);
}
}
2.监听器类或方法添加@Async注解
打印结果:
订单创建成功
finished!
heling,您的订单:123456789创建成功! ----by sms
heling,您的订单:123456789创建成功! ----by wechat
如何制定监听器执行顺序?
package com.pengshu.magicwallet.admin.test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.stereotype.Component;
/**
* Author heling on 2019/1/9
* 微信监听器
* SmartApplicationListener可以设置顺序等
*/
@Component
public class WechatListener implements SmartApplicationListener {
//设置监听优先级
@Override
public int getOrder() {
return 1;
}
//监听器智能所在之一,能够根据事件类型动态监听
@Override
public boolean supportsEventType(Class extends ApplicationEvent> aClass) {
return aClass == OrderCreateEvent.class;
}
//监听器智能所在之二,能够根据事件发布者类型动态监听
@Override
public boolean supportsSourceType(Class> aClass) {
return aClass == OrderServiceImpl.class;
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
OrderCreateEvent event = (OrderCreateEvent) applicationEvent;
//发送微信
System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by wechat");
}
// @Override
// @Async
// public void onApplicationEvent(OrderCreateEvent event) {
//
// //发送微信
// System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by wechat");
//
// }
}
package com.pengshu.magicwallet.admin.test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.stereotype.Component;
/**
* Author heling on 2019/1/9
* 短信监听器
*/
@Component
public class SmsListener implements SmartApplicationListener {
@Override
public int getOrder() {
return 2;
}
@Override
public boolean supportsEventType(Class extends ApplicationEvent> aClass) {
return aClass == OrderCreateEvent.class;
}
@Override
public boolean supportsSourceType(Class> aClass) {
return aClass == OrderServiceImpl.class;
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
OrderCreateEvent event = (OrderCreateEvent) applicationEvent;
//发送短信
System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by sms");
}
// @Override
// @Async
// public void onApplicationEvent(OrderCreateEvent event) {
//
// //发送短信
// System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by sms");
//
// }
}
打印结果:
订单创建成功
heling,您的订单:123456789创建成功! ----by wechat
heling,您的订单:123456789创建成功! ----by sms
finished!
在实现了SmartApplicationListener的监听器中,我们通过重写GetOrder方法来修改不同监听器的顺序,优先级越小,则越先被调用。通过配置不同的优先级,且让监听器之间阻塞调用。我们就能实现流水线式的有序事件调用,这在实际应用场景中还是蛮有意义的