以創建訂單爲例,需要增加短信通知和事物通知,每次寫一個service也可以,最好的方式可以使用spring的事件監聽。
spring監聽器的使用:定義事件實現applicationEvent 定義監聽器是實現smartApplicationListener<> 發佈事件:applicationContext.publishEvent(orderCreateEvent)
https://blog.csdn.net/weixin_39035120/article/details/86225377
以下僞代碼是一個保存訂單的功能,並會發送短信消息:
/**
* 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<String> contentList;
public OrderCreateEvent(Object source, String name, List<String> contentList) {
super(source);
this.name = name;
this.contentList = contentList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getContentList() {
return contentList;
}
public void setContentList(List<String> 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<OrderCreateEvent> {
@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<OrderCreateEvent> {
@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<String> 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方法來修改不同監聽器的順序,優先級越小,則越先被調用。通過配置不同的優先級,且讓監聽器之間阻塞調用。我們就能實現流水線式的有序事件調用,這在實際應用場景中還是蠻有意義的
————————————————
版權聲明:本文爲CSDN博主「超人不會飛2018」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_39035120/article/details/86225377