spring事件驱动模型--观察者模式在spring中的应用

简介:   spring中的事件驱动模型也叫作发布订阅模式,是观察者模式的一个典型的应用,关于观察者模式在之前的博文中总结过,http://www.cnblogs.com/fingerboy/p/5468994.

  spring中的事件驱动模型也叫作发布订阅模式,是观察者模式的一个典型的应用,关于观察者模式在之前的博文中总结过,http://www.cnblogs.com/fingerboy/p/5468994.html  这里主要讲一下Spring中的观察者模式的应用.

spring事件驱动模型的结构.

  

  首先明确几个spring提供的类的概念

  1.ApplicationEvent

public abstract class ApplicationEvent extends EventObject {
    private static final long serialVersionUID = 7099057708183571937L;
    private final long timestamp;
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }
    public final long getTimestamp() {
        return this.timestamp;
    }
}

  ApplicationEvent继承自jdk的EventObject,所有的事件都需要继承ApplicationEvent,并且通过source得到事件源.该类的实现类ApplicationContextEvent表示ApplicaitonContext的容器事件.

  2.ApplicationListener

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

  ApplicationListener继承自jdk的EventListener,所有的监听器都要实现这个接口,这个接口只有一个onApplicationEvent()方法,该方法接受一个ApplicationEvent或其子类对象作为参数,在方法体中,可以通过不同对Event类的判断来进行相应的处理.当事件触发时所有的监听器都会收到消息,如果你需要对监听器的接收顺序有要求,可是实现该接口的一个实现SmartApplicationListener,通过这个接口可以指定监听器接收事件的顺序.

  3.ApplicationContext

   事件机制的实现需要三个部分,事件源,事件,事件监听器,在上面介绍的ApplicationEvent就相当于事件,ApplicationListener相当于事件监听器,这里的事件源说的就是applicaitonContext.

   ApplicationContext是spring中的全局容器,翻译过来是"应用上下文"的意思,它用来负责读取bean的配置文档,管理bean的加载,维护bean之间的依赖关系,可以说是负责bean的整个生命周期,再通俗一点就是我们平时所说的IOC容器. 

      Application作为一个事件源,需要显示的调用publishEvent方法,传入一个ApplicationEvent的实现类对象作为参数,每当ApplicationContext发布ApplicationEvent时,所有的ApplicationListener就会被自动的触发.

  ApplicationContext接口实现了ApplicationEventPublisher接口,后者有一个很重要的方法:

public interface ApplicationEventPublisher {
    void publishEvent(ApplicationEvent event);
}

  我们常用的ApplicationContext都继承了AbstractApplicationContext,像我们平时常见的ClassPathXmlApplicationContext、XmlWebApplicationContex也都是继承了它,AbstractApplicationcontext是ApplicationContext接口的抽象实现类,在该类中实现了publishEvent方法

public void publishEvent(ApplicationEvent event) {
        Assert.notNull(event, "Event must not be null");
        if (logger.isTraceEnabled()) {
            logger.trace("Publishing event in " + getDisplayName() + ": " + event);
        }
        getApplicationEventMulticaster().multicastEvent(event);
        if (this.parent != null) {
            this.parent.publishEvent(event);
        }
    }

  在这个方法中,我们看到了一个getApplicationEventMulticaster().这就要牵扯到另一个类ApplicationEventMulticaster.

  4.ApplicationEventMulticaster

  属于事件广播器,它的作用是把Applicationcontext发布的Event广播给所有的监听器.

  在AbstractApplicationcontext中有一个applicationEventMulticaster的成员变量,提供了监听器Listener的注册方法.

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext, DisposableBean {

  private ApplicationEventMulticaster applicationEventMulticaster;
  protected void registerListeners() {
        // Register statically specified listeners first.
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String lisName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(lisName);
        }
    }
}

 在Spring 中使用事件监听机制的Demo

  1. 建立事件类,继承applicationEvent

public class MyEvent extends ApplicationEvent {

    public MyEvent(Object source) {
        super(source);
        System.out.println("my Event");
    }
    public void print(){
        System.out.println("hello spring event[MyEvent]");
    }
}

  2.建立监听类,实现ApplicationListener接口

public class MyListener  implements ApplicationListener{
    
    public void onApplicationEvent(ApplicationEvent event) {
        if(event instanceof MyEvent){
            System.out.println("into My Listener");
            MyEvent myEvent=(MyEvent)event;
            myEvent.print();
        }
    }
}

这里再建一个监听类

public class MyListener  implements ApplicationListener{
    
    public void onApplicationEvent(ApplicationEvent event) {
        if(event instanceof MyEvent){
            System.out.println("into My Listener");
            MyEvent myEvent=(MyEvent)event;
            myEvent.print();
        }
    }
}

  3.创建一个发布事件的类,该类实现ApplicationContextAware接口,得到ApplicationContext对象,使用该对象的publishEvent方法发布事件.

public class MyPubisher implements ApplicationContextAware {

    private ApplicationContext applicationContext;
    
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
    public void publishEvent(ApplicationEvent event){
        System.out.println("into My Publisher's method");
        applicationContext.publishEvent(event);
    }
}

  3.在spring配置文件中,注册事件类和监听类,当然使用注解的方式也是一样的.(略)

  4.测试

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("classpath:spring/application-database.xml");
        MyPubisher myPubisher=(MyPubisher) context.getBean("myPublisher");
        myPubisher.publishEvent(new MyEvent("1"));
    }
}

  查看控制台打印

my Event

into My Publisher's method

into My Listener
hello spring event[MyEvent]
into My second Listener
hello spring event[MyEvent]

总结

  spring的事件驱动模型使用的是 观察者模式

  通过ApplicationEvent抽象类和ApplicationListener接口,可以实现ApplicationContext事件处理

  监听器在处理Event时,通常会进行判断传入的Event是不是自己所想要处理的,使用instanceof关键字

  ApplicationEventMulticaster事件广播器实现了监听器的注册,一般不需要我们实现,只需要显示的调用applicationcontext.publisherEvent方法即可

 

相关文章
|
2月前
|
监控 Java 数据处理
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
|
3月前
|
XML Java 数据格式
Spring 应用上下文探秘:生命周期解析与最佳实践
Spring 应用上下文探秘:生命周期解析与最佳实践
75 0
|
3月前
|
存储 Java Maven
QR码应用实战:Spring Boot与ZXing完美结合
QR码应用实战:Spring Boot与ZXing完美结合
32 0
|
2月前
|
人工智能 JSON 前端开发
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
|
3月前
|
消息中间件 存储 监控
搭建消息时光机:深入探究RabbitMQ_recent_history_exchange在Spring Boot中的应用【RabbitMQ实战 二】
搭建消息时光机:深入探究RabbitMQ_recent_history_exchange在Spring Boot中的应用【RabbitMQ实战 二】
34 1
|
2月前
|
安全 Java 数据安全/隐私保护
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
67 1
|
3月前
|
消息中间件 NoSQL Java
Redis Streams在Spring Boot中的应用:构建可靠的消息队列解决方案【redis实战 二】
Redis Streams在Spring Boot中的应用:构建可靠的消息队列解决方案【redis实战 二】
251 1
|
4天前
|
监控 Java Sentinel
Spring Cloud Sentinel:概念与实战应用
【4月更文挑战第28天】在分布式微服务架构中,确保系统的稳定性和可靠性至关重要。Spring Cloud Sentinel 为微服务提供流量控制、熔断降级和系统负载保护,有效预防服务雪崩。本篇博客深入探讨 Spring Cloud Sentinel 的核心概念,并通过实际案例展示其在项目中的应用。
13 0
|
6天前
|
XML Java 数据格式
手写spring第六章-实现应用上下文,完成bean的扩展机制
手写spring第六章-实现应用上下文,完成bean的扩展机制
12 0
|
8天前
|
消息中间件 Java 中间件
第十六章 Spring cloud stream应用
第十六章 Spring cloud stream应用
14 0