Spring自定义事件发布-监听

    技术2022-07-11  108

    本人Git地址:https://github.com/a422478514/java-practice/tree/master/src/main/java/com/daquan/_202007/_01/spring/event

    一、监听器模式

    监听者通过向发布者注册自身(自身可以理解为监听者对象),如果有事件发生,发布者会调用注册列表里的监听者的某方法并把事件(事件内部持有事件源)作为参数传入。

    在Spring中需要我们自己定义事件监听器、事件。发布器不需要自定义,但需要设法通过上下文拿到发布器。(可以思考下为什么这么设计?)

    二、基于Spring实现的消息监听类图详解

    1、事件:

    EventObject:是JDK自带的事件,是个具体的类,本身持有一个Object事件源用来定义本次事件的具体描述。EventObject本身是事件源的容器。

    ApplicationEvent:是对EventObject的简单封装(扩展),但是是个抽象类,用来作为自定义事件类的基类,这样设计也是为了满足对监听器对具体某自定义事件的监听。该类构造函数里调用了super(source)用来封装事件源,并提供了一个返回当前时间的方法。

    MySpringApplicationEvent:是自定义的事件类,也是本次讲解中要被监听的事件。其构造函数需要的参数同样是自定义的事件源。

    2、发布者容器:

    Aware是个空接口,用来方便扩展,也是Spring的惯用操作

    ApplicationEventPublisherAware是Spring中用来识别注入ApplicationEventPublisher对象的特殊接口。(一般xxxxxAware都是用来给实现类注入xxxxx的)

    MySpringEventPublisherContext是自定义的发布者容器,里面封装了Spring提供的事件发布器

    3、监听者

    EventListener:Spring提供的空接口

    ApplicationListener:继承了EventListener且通过使用泛型来实现针对某一具体事件类型的监听,onApplicationEvent作为事件触发时调用的函数。

    4、自定义事件源

    MyEventSource是事件源的具体实现,是事件的核心内容,该类持有大部分有效信息。

    三、代码

    1、MyEventSource.java

    /** * 用来描述事件源的实体类 */ public class MyEventSource implements Serializable { private static final long serialVersionUID = 1L; private int id; private String name; public MyEventSource(int id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "MyEventSource{" + "id=" + id + ", name='" + name + '\'' + '}'; } }

    2、MySpringApplicationEvent.java

    import org.springframework.context.ApplicationEvent; /** * 使用spring事件框架自定义的事件 */ public class MySpringApplicationEvent extends ApplicationEvent { public MySpringApplicationEvent(MyEventSource eventSource) { super(eventSource); } }

    3、MySpringApplicationListener.java

    import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Service; /** * 基于Spring事件框架自定义的事件监听器,注意泛型用来确定要监听的事件 */ @Service public class MySpringApplicationListener implements ApplicationListener<MySpringApplicationEvent> { @Override public void onApplicationEvent(MySpringApplicationEvent mySpringApplicationEvent) { System.out.println("监听到事件:"+mySpringApplicationEvent.getSource().toString()); } }

    4、MySpringEventPublisherContext.java

    import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.stereotype.Service; /** * 事件发布器上下文 */ @Service public class MySpringEventPublisherContext implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { System.out.println("注入事件发布器"); this.applicationEventPublisher = applicationEventPublisher; } public ApplicationEventPublisher getApplicationEventPublisher() { return applicationEventPublisher; } }

    5、TestSpringEventMain.java

    import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 测试SpringEvent的启动器 */ public class TestSpringEventMain { public static void main(String[] args) { System.out.println("1、加载spring容器"); ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("application.xml"); System.out.println("2、从容器中获取事件发布器"); MySpringEventPublisherContext publisherContext = classPathXmlApplicationContext.getBean(MySpringEventPublisherContext.class); System.out.println("3、发布事件"); publisherContext.getApplicationEventPublisher().publishEvent(new MySpringApplicationEvent(new MyEventSource(1,"daquan"))); } }

    6、配置文件 application.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <context:annotation-config /> <!--自动扫描含有@Service将其注入为bean --> <context:component-scan base-package="com.daquan._202007" /> </beans>

    运行5、结果如下:

    Processed: 0.010, SQL: 9