栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ApplicationContext-监听器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ApplicationContext-监听器

《BeanFactory与ApplicationContext的区别》说明了BeanFactory的延迟实例化以及ApplicationContext的不延迟实例化。同时,也说明了ApplicationContext特有功能的前三个(国际化、资源访问、载入多个上下文),今天学习下ApplicationContext的事件机制。

概述

ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。

两个重要成员:

  • ApplicationEvent:容器事件,必须由ApplicationContext发布;
  • ApplicationListener:监听器,可由容器中的任何监听器Bean担任。
1. 定义容器事件

定义一个邮件事件EmailEvent:

package appContextDemo;
import org.springframework.context.ApplicationEvent;

public class EmailEvent extends ApplicationEvent {
    public String address;
    public String context;

    public EmailEvent(Object source) {
        super(source);
    }

    public EmailEvent(Object source, String address, String context) {
        super(source);
        this.address = address;
        this.context = context;
    }

    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getContext() {
        return context;
    }
    public void setContext(String context) {
        this.context = context;
    }
}

EmailEvent类继承了ApplicationEvent类,除此之外,它就是一个普通的Java类 。

2. 定义监听器

为了效果我们定义两个监听器EmailListener、EmailListener2
EmailListener:

package appContextDemo;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class EmailListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if (applicationEvent instanceof EmailEvent){
            EmailEvent emailEvent = (EmailEvent) applicationEvent;
            System.out.println("EmailListener 收到 email's address:"+ emailEvent.getAddress());
            System.out.println("EmailListener 收到 email's text:"+ emailEvent.getContext());
        }else {
            System.out.println("the Spring's event:"+ applicationEvent);
        }
    }
}

EmailListener2:

package appContextDemo;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class EmailListener2 implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if (applicationEvent instanceof EmailEvent){
            EmailEvent emailEvent = (EmailEvent) applicationEvent;
            System.out.println("EmailListener2 收到 email's address:" + emailEvent.getAddress());
            System.out.println("EmailListener2 收到 email's text:" + emailEvent.getContext());
        }else {
            System.out.println("the Spring's event:"+ applicationEvent);
        }
    }
}
3. 将监听器注入到spring容器

applicationContext.xml:



    
    
    
    
    

4. 发布事件

ListenerTest:

package appContextDemo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ListenerTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("appContextDemo/applicationContext.xml");
        
        EmailEvent emailEvent = new EmailEvent("随便传值", "cupd@163.com", "This is SpringApplicatoinContext test!");
        System.out.println("事件创建成功");
        
        context.publishEvent(emailEvent);
    }
}

运行结果:

publishEvent(ApplicationEvent var1);方法用于ApplicationContext发布事件。

发布监听

上述说明了Spring监听器实现步骤,只是理论知识,下面结合业务场景说明Spring监听机制。
场景:

用户在网上商城下单成功后,平台要发送短信通知用户下单成功。

一般实现如下:

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

过了段时间,添加新功能,用户下单成功后,平台需要通知物流系统发货

增加物流发货功能:

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

又过了一段时间,需要删除物流发货功能,你可能需要把 notifyCar(); 注释。然后产品功能又调整,又要添加物流发货功能。反反复复,对订单功能反复修改,保不准会有什么bug,而且也不符合“开闭原则”。
而Spring监听机制提供一种 “以增量的方式应对变化的需求” 思路。

项目层级:

订单服务

OrderService:

package appContextDemo.service;
import appContextDemo.event.OrderSuccessEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;


@Service
public class OrderService {

    @Autowired
    private ApplicationContext applicationContext;

    public void order() {
        
        System.out.println("下单成功...");
        
        applicationContext.publishEvent(new OrderSuccessEvent("发布OrderSuccessEvent事件"));
        System.out.println("main线程结束...");
    }
}
定义事件

OrderSuccessEvent:

package appContextDemo.event;
import org.springframework.context.ApplicationEvent;

public class OrderSuccessEvent extends ApplicationEvent {

    public OrderSuccessEvent(Object source) {
        super(source);
    }
}
定义发送短信监听器

SmsService :

package appContextDemo.service;
import appContextDemo.event.OrderSuccessEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;


@Service
public class SmsService implements ApplicationListener {
    @Override
    public void onApplicationEvent(OrderSuccessEvent event) {
        this.sendSms();
    }
    
    
    public void sendSms() {
        System.out.println("发送短信...");
    }
}
将监听器注入到spring容器

applicationContext.xml:




    

测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:appContextDemo/applicationContext.xml")
public class TestSpring {
    @Autowired
    OrderService orderService;

    @Test
    public void test(){
        orderService.order();
    }
}

运行结果:

如果后期针对下单成功有新的操作,可以新写一个事件监听类。
新增物流服务CarService :

@Service
public class CarService  implements ApplicationListener {
    @Override
    public void onApplicationEvent(OrderSuccessEvent event) {
        this.dispatch();
    }

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

运行结果:

这就是“以增量的方式应对变化的需求”,而不是去修改已有的代码。符合“对扩展开放,对修改关闭”的原则。通过发布事件,触发该事件上所有监听服务。
但是结果可以看到,SmsService 是在 CarService之后执行,显然不符合我们业务逻辑,那怎么让监听器按照配置的顺序执行呢? 请看下文。

顺序监听

如果需要执行顺序,Spring提供 SmartApplicationListener 与 GenericApplicationListener 可供选择。以SmartApplicationListener为例。

包含3个实现方法。支持的类型,支持的事件类,执行顺序。

  • supportsEventType:用于指定支持的事件类型,只有支持的才调用onApplicationEvent;
  • supportsSourceType:支持的目标类型,只有支持的才调用onApplicationEvent;
  • getOrder:即顺序,越小优先级越高
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/685741.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号