spring监听功能的使用

以创建订单为例,需要增加短信通知和事物通知,每次写一个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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值