spring事件传播机制------基于观察者模式

前言

这几天看sping和springboot的一些高级应用,有所感悟,spring框架发展已经将近20年了,还像一个小伙子一样年轻,我们可以看到,它在不断地的扩展和更新,二以前的struts等,早已是日落西山,基本没人用了,那么,为什么,就是因为spring框架设计的好,使得扩展成为了可能,同时容易维护,现在想一个问题,我们的项目可以维护20年吗?显然这是不太可能的,几年的项目就改的稀巴烂,所以,我们写项目的时候,如果学习spring等一些优秀框架的设计思想,那么我们的程序应该符合软件的设计原则等等,概念性的东西就不说了,下面从一个小小的例子入手

问题:

我们要在下边创建订单后,增加发送短息给客户的功能,怎么做?
伪代码如下

public void order(){
		// 逻辑省略了,其中代码可能会很长。
        System.out.println("1.创建订单,下单成功");

    }

增加发送短信

常规操作,直接在订单完成之后,增加发送信息功能

public void order(){
        System.out.println("1.创建订单,下单成功");
        // 伪代码,具体怎么发送,逻辑很多
        System.out.println("2. 发送短信成功");
    }

好,那么这样就完成了,看起来没什么问题,但如果过来一段时间,还有增加发送邮件的功能,继续操作,增加代码

public void order(){
        System.out.println("1.创建订单,下单成功");
        // 伪代码,具体怎么发送,逻辑很多
        System.out.println("2. 发送短信成功");
		System.out.println("3. 发送邮件成功");
    }
问题来了

这样操作,不断地修改原来的代码,来扩展功能,不符合我们的设计原则,应该对扩展开启,对修改关闭。
怎么做?
这个问题交给观察者模式设计解决。

spring 中event的应用

spring中有这样一个接口 ApplicationListener,实现这个接口,可以让我们在springboot启动的时候额外的做一些其他事情,很明显,这是个监听者,
示例看一下:

@Component
public class StartUpListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("springboot启动时,执行一些任务。。。。。。。");
    }
}

启动springboot,我们看到

2019-09-16 00:01:47.110 INFO 19900 — [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService ‘applicationTaskExecutor’
springboot启动时,执行一些任务。。。。。。。
2019-09-16 00:01:47.486 INFO 19900 — [ main] com.example.demo.DemoApplicationTests : Started DemoApplicationTests in 2.942 seconds (JVM

说明一下:
ContextRefreshedEvent 是项目启动的事件,这里只不过绑定了这个事件。

那么我们就可以按照这个设计思想,自定义我们自己的事件,然后监听,就可以添加额外的功能了。

改造短信的功能

定义orderEvent事件
public class OrderEvent extends ApplicationEvent {
    public OrderEvent(Object source) {
        super(source);
    }
}

思考一个问题。为什么继承这个类 ApplicationEvent?

定义发送短信的监听者和发送邮件的监听者
@Component
public class SMService implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent orderEvent) {
        System.out.println("2 发送短信成功");
    }
}
@Component
public class MailService implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent orderEvent) {
        System.out.println("3. 邮件发送成功。");
    }
}

在观察者模式中,事件通知还要加上

改造orderService
@Service
public class OrderService {
    @Autowired
    ApplicationContext applicationContext;
    public void order(){
        System.out.println("1.创建订单,下单成功");
        OrderEvent orderEvent = new OrderEvent("随便一个参数");
        applicationContext.publishEvent(orderEvent);
    }
}

这里我们通过 applicationContext 上下文将事件发布了,所有监听了事件的观察者就可以收到。

  • 单元测试下
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
    @Autowired
    OrderService orderService;
    @Test
    public void contextLoads() {
        orderService.order();
    }
}

  • 结果

1.创建订单,下单成功
3. 邮件发送成功。
2 发送短信成功

这时候,又有一个新的问题了,我们期望的结果是先发送短信,后发邮件,这样处理。

@Component
public class SMService implements ApplicationListener<OrderEvent> ,Ordered{
    @Override
    public void onApplicationEvent(OrderEvent orderEvent) {
        System.out.println("2 发送短信成功");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
@Component
public class MailService implements ApplicationListener<OrderEvent> ,Ordered{
    @Override
    public void onApplicationEvent(OrderEvent orderEvent) {
        System.out.println("3. 邮件发送成功。");
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

多实现一个接口,这个提供了顺序,自己设置下就行了
结果:

1.创建订单,下单成功
2 发送短信成功
3. 邮件发送成功。

  • 特别说明一下,以下这样的也是可以的,不过SmartApplicationListener 这个类,在springboot 2.1.8 和之前的版本好像有点不一样,大家可以注意下
@Component
public class MailService implements SmartApplicationListener{
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
        return aClass==OrderEvent.class;
    }
    @Override  
    public int getOrder() {
        return 1;
    }
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        System.out.println("3 邮件发送成功");
    }
}

最后回答下,上面的问题,为什么定义的事件只能继承ApplicationEvent,因为ApplicationListener 的泛型类就是 继承了 ApplicationEvent

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E var1);
}

我是在springboot上,用一些理解写的,可能有些术语不太规范,欢迎指正!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值