前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Spring] Spring 容器事件

[Spring] Spring 容器事件

作者头像
架构探险之道
发布2019-12-17 18:08:01
4520
发布2019-12-17 18:08:01
举报
文章被收录于专栏:架构探险之道

[Spring] Spring 容器事件

手机用户请横屏获取最佳阅读体验,REFERENCES中是本文参考的链接,如需要链接和更多资源,可以关注其他博客发布地址。

平台

地址

CSDN

https://blog.csdn.net/sinat_28690417

简书

https://www.jianshu.com/u/3032cc862300

个人博客

https://yiyuery.github.io/NoteBooks/

Spring 的 ApplicaitonContext 能够发布事件并允许注册相应的事件监听器。

事件体系

  • 事件源
  • 事件监听注册表
  • 事件广播器

顾名思义:事件源即被传播的消息体,事件监听者都需要在事件监听注册表中登记。这样,在事件到来时,事件广播器负责将事件源信息根据监听表中登记的信息,进行分发。

设计结构

事件类

在这里插入图片描述

  • ApplicationContextEvent 容器事件,四个子类,分别代表容器的启动、刷新、停止和关闭事件
  • RequestHandledEvent Web 应用相关事件,当一个HTTP请求被处理后,产生该事件,只有在web.xml中定义了DispatchServlet时才会产生该事件,拥有2个之类,分别代表Servlet和Portlet的事件

另外,支持通过ApplicationEvent 扩展自定义事件。

事件监听接口

Spring 的事件监听器都继承ApplicationListenner接口

在这里插入图片描述

代码语言:javascript
复制
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

    /**
     * Handle an application event.
     * @param event the event to respond to
     */
    void onApplicationEvent(E event);

}

用于接收ApplicationEvent及其子类。

在Spring 3.0 中新增一个增强类SmartApplicationListener

代码语言:javascript
复制
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {

    /**
     * Determine whether this listener actually supports the given event type.
     * @param eventType the event type (never {@code null})
     */
    boolean supportsEventType(Class<? extends ApplicationEvent> eventType);

    /**
     * Determine whether this listener actually supports the given source type.
     * <p>The default implementation always returns {@code true}.
     * @param sourceType the source type, or {@code null} if no source
     */
    default boolean supportsSourceType(@Nullable Class<?> sourceType) {
        return true;
    }

    /**
     * Determine this listener's order in a set of listeners for the same event.
     * <p>The default implementation returns {@link #LOWEST_PRECEDENCE}.
     */
    @Override
    default int getOrder() {
        return LOWEST_PRECEDENCE;
    }

}

新增2个方法

  • boolean supportsEventType(Class eventType) 用于指定事件类型进行过滤。
  • boolean supportsSourceType(@Nullable Class sourceType) 用于对指定事件源对象进行过滤

在Spring 4.2 中新增一个增强类GenericApplicationListener,与之前SmartApplicationListener接口不同的是,同时增强对泛型事件类型的支持,supportsSourceType()方法的参数不再仅仅支持ApplicationEvent及其子类,而是采用可解析类型ResolvableType。

代码语言:javascript
复制
public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {

    /**
     * Determine whether this listener actually supports the given event type.
     * @param eventType the event type (never {@code null})
     */
    boolean supportsEventType(ResolvableType eventType);

    /**
     * Determine whether this listener actually supports the given source type.
     * <p>The default implementation always returns {@code true}.
     * @param sourceType the source type, or {@code null} if no source
     */
    default boolean supportsSourceType(@Nullable Class<?> sourceType) {
        return true;
    }

    /**
     * Determine this listener's order in a set of listeners for the same event.
     * <p>The default implementation returns {@link #LOWEST_PRECEDENCE}.
     */
    @Override
    default int getOrder() {
        return LOWEST_PRECEDENCE;
    }

}
  • boolean supportsEventType(ResolvableType eventType) 用于指定事件类型进行过滤,可以通过该类获取事件对象的具体信息。
  • boolean supportsSourceType(@Nullable Class sourceType) 用于对指定事件源对象进行过滤

事件广播器

在这里插入图片描述

当容器事件发生时,容器主控程序将调用事件广播器将事件通知给事件监听器注册表中的事件监听器。事件监听器分别根据自身实现对所关注的事件进行响应。

Spring为其提供了默认的实现类SimpleApplicationEventMulticaster.

代码实战

Spring 容器事件实战 代码 build.gradle

代码语言:javascript
复制
buildscript {
    repositories {
        maven { url = "https://plugins.gradle.org/m2/" }
        maven { url = "http://maven.aliyun.com/nexus/content/groups/public/" }
        jcenter()
    }
    dependencies {
        classpath libs["spring-boot-gradle-plugin"]
    }
}

apply plugin: "io.spring.dependency-management"
apply plugin: "org.springframework.boot"

bootJar {
    baseName = 'common-boot-support'
    version = '1.0.0'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compile project(':common-dependencies:common-web-template')
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testCompile("org.junit.jupiter:junit-jupiter-api")
    testRuntime("org.junit.jupiter:junit-jupiter-engine")
}

BusinessEventListener.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 5:34 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.listener;

import com.example.spring.event.common.EventSourceTypeEnum;
import com.example.spring.event.sender.MailSender;
import com.example.spring.event.source.BusinessEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.stereotype.Component;

/**
 * <p>
 * SmartApplicationListener
 * 消息监听【支持类型简单过滤】
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 5:34 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Component
public class BusinessEventListener implements SmartApplicationListener {

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return BusinessEvent.class.equals(eventType);
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        BusinessEvent ev = ((BusinessEvent) event);
        if (EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_1.equals(ev.getSourceType())) {
            System.out.println("BusinessEventListener 收到消息 "+ev.getEventSource()+ ev.getMessage());
        }else{
            System.out.println("BusinessEventListener 忽略消息"+ev.getEventSource()+ ev.getMessage());
        }
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        System.out.println("BusinessEventListener 事件源"+sourceType.getName());
        return true;
    }
}

BusinessGenericEventListener.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 8:21 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.listener;

import com.example.spring.event.common.EventSourceTypeEnum;
import com.example.spring.event.source.BusinessEvent;
import com.example.spring.event.source.GenericBusinessEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;

/**
 * <p>
 *  GenericApplicationListener
 *  消息监听【支持类型具体信息解析ResolvableType过滤】
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 8:21 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Component
public class BusinessGenericEventListener implements GenericApplicationListener {

    @Override
    public boolean supportsEventType(ResolvableType eventType) {
        return eventType.isAssignableFrom(GenericBusinessEvent.class);
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        System.out.println("BusinessGenericEventListener 事件源"+sourceType.getName());
        return true;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        GenericBusinessEvent ev = ((GenericBusinessEvent) event);
        if (EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_1.equals(ev.getSourceType())) {
            System.out.println("BusinessGenericEventListener 收到消息 "+ev.getEventSource()+ ev.getMessage());
        }else{
            System.out.println("BusinessGenericEventListener 忽略消息"+ev.getEventSource()+ ev.getMessage());
        }
    }
}

MailSendListener.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 4:39 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.listener;

import com.example.spring.event.source.MailSendEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 普通消息监听【不支持类型过滤,需要自定义消息结构来实现过滤的逻辑】
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 4:39 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Component
public class MailSendListener implements ApplicationListener<MailSendEvent> {

    @Override
    public void onApplicationEvent(MailSendEvent event) {
        System.out.println("MailSendListener 收到一份邮件:" + event.getMessage());
    }
}

SpringEventApplication.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 2:34 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * <p>
 * 启动类
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 2:16 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@SpringBootApplication
@ComponentScan(basePackages = {"com.example"})
public class SpringEventApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringEventApplication.class);
    }
}

BusinessEvent.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 5:52 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.source;

import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ApplicationContextEvent;

import javax.swing.*;

/**
 * <p>
 * 业务事件源
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 5:52 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
public class BusinessEvent extends AbstractMessageEvent {

    @Override
    public String getEventSource() {
        return this.getClass().getName();
    }

    public BusinessEvent(ApplicationContext source) {
        super(source);
    }
}

AbstractMessageEvent.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 5:53 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.source;

import com.example.spring.event.common.EventSourceTypeEnum;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ApplicationContextEvent;

/**
 * <p>
 *  抽象事件源定义
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 5:53 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Getter
@Setter
public abstract class AbstractMessageEvent extends ApplicationContextEvent {

    private String message;

    private EventSourceTypeEnum sourceType = EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_1;

    public abstract String getEventSource();

    /**
     * Create a new ContextStartedEvent.
     *
     * @param source the {@code ApplicationContext} that the event is raised for
     *               (must not be {@code null})
     */
    public AbstractMessageEvent(ApplicationContext source) {
        super(source);
    }

    public AbstractMessageEvent(ApplicationContext source, String message) {
        super(source);
        setMessage(message);
    }
}

GenericBusinessEvent.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 8:32 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.source;

import com.example.spring.event.common.EventSourceTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationContext;

/**
 * <p>
 *  事件源
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 8:32 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Getter
@Setter
public class GenericBusinessEvent extends AbstractMessageEvent{

    public GenericBusinessEvent(ApplicationContext source) {
        super(source);
    }

    public GenericBusinessEvent(ApplicationContext source, String message) {
        super(source, message);
    }

    @Override
    public String getEventSource() {
        return this.getClass().getName();
    }
}

MailSendEvent.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 4:37 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.source;

import lombok.Getter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ApplicationContextEvent;

/**
 * <p>
 * 事件源:Email 消息体
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 4:37 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Getter
public class MailSendEvent extends ApplicationContextEvent {

    private String message;

    /**
     * Create a new ContextStartedEvent.
     *
     * @param source the {@code ApplicationContext} that the event is raised for
     *               (must not be {@code null})
     */
    public MailSendEvent(ApplicationContext source) {
        super(source);
    }
    /**
     * Create a new ContextStartedEvent.
     *
     * @param source the {@code ApplicationContext} that the event is raised for
     *               (must not be {@code null})
     */
    public MailSendEvent(ApplicationContext source,String message) {
        super(source);
        this.message = message;
    }
}

MailSender.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 4:42 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.sender;

import com.example.spring.event.source.MailSendEvent;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 指定Email 消息发送
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 4:42 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Setter
@Getter
@Slf4j
@Component
public class MailSender implements ApplicationContextAware {

    private ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        setCtx(applicationContext);
    }

    public void sendMail(String message) {
        log.info("MailSender 发送短信...");
        ctx.publishEvent(new MailSendEvent(getCtx(),message));
    }
}

EventPublisher.java

代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 6:00 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.example.spring.event.sender;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 消息发送者
 * </p>
 *
 * @author xiazhaoyang
 * @version V1.0.0
 * @date 2019/12/8 6:00 下午
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人}  2019/12/8
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Component
@Setter
@Getter
public class EventPublisher implements ApplicationContextAware {

    private ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        setCtx(applicationContext);
    }

    public void sendMessage(ApplicationContextEvent event) {
        System.out.println("EventPublisher 开始发送" + event.getClass().getName());
        ctx.publishEvent(event);
    }
}

EventSourceTypeEnum.java

代码语言:javascript
复制
package com.example.spring.event.common;/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 5:49 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum EventSourceTypeEnum {

    EVENT_SOURCE_TYPE_ENUM_BUSINESS_1,
    EVENT_SOURCE_TYPE_ENUM_BUSINESS_2;
}

测试

代码语言:javascript
复制
package com.example.spring.event;

import com.example.spring.event.common.EventSourceTypeEnum;
import com.example.spring.event.sender.EventPublisher;
import com.example.spring.event.sender.MailSender;
import com.example.spring.event.source.BusinessEvent;
import com.example.spring.event.source.MailSendEvent;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import static org.junit.Assert.*;

/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
 * @address:     https://yiyuery.github.io/NoteBooks/
 * @date:        2019/12/8 4:46 下午
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
@SpringBootTest
@ComponentScan(basePackages = {"com.example"})
public class SpringEventApplicationTest {

    @Resource
    private MailSender mailSender;
    @Resource
    private EventPublisher eventPublisher;

    /**
     * 测试消息 直接定义发送信息处理对象来进行发送
     */
    @Test
    public void mailSender() {
        mailSender.sendMail("Hello Testing");
    }

    /**
     * 抽离发送逻辑,构造消息发送器
     * - 发送Hello Testing"
     * - 发送自定义业务消息[扩展事件抽象类,定义统一的业务基本属性信息]
     */
    @Test
    public void smartSender() {
        mailSender.sendMail("Hello Testing");

        eventPublisher.sendMessage(new MailSendEvent(eventPublisher.getCtx(),"Hello Testing Again! "));

        BusinessEvent businessEvent = new BusinessEvent(eventPublisher.getCtx());
        businessEvent.setMessage("eventPublisher 发送 businessEvent ");
        businessEvent.setSourceType(EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_1);
        eventPublisher.sendMessage(businessEvent);
    }

    /**
     * 测试消息发送和忽略
     */
    @Test
    public void smartSenderAndIgnore() {
        //直接定义对应的发送类发送
        mailSender.sendMail("Hello Testing");

        //定义公共事件发送
        eventPublisher.sendMessage(new MailSendEvent(eventPublisher.getCtx(),"Hello Testing Again! "));

        //发送业务事件 && 不被忽略
        BusinessEvent businessEvent = new BusinessEvent(eventPublisher.getCtx());
        businessEvent.setMessage("eventPublisher 发送 businessEvent ");
        businessEvent.setSourceType(EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_1);
        eventPublisher.sendMessage(businessEvent);

        //发送其他业务事件 && 被忽略
        BusinessEvent businessEvent2 = new BusinessEvent(eventPublisher.getCtx());
        businessEvent2.setMessage("eventPublisher 发送 businessEvent and has been ignored");
        businessEvent2.setSourceType(EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_2);
        eventPublisher.sendMessage(businessEvent2);
    }
    /**
     * 测试消息发送和忽略
     */
    @Test
    public void genericSenderAndIgnore() {
        //直接定义对应的发送类发送
        mailSender.sendMail("Hello Testing");

        //定义公共事件发送
        eventPublisher.sendMessage(new MailSendEvent(eventPublisher.getCtx(),"Hello Testing Again! "));

        //发送业务事件 && 不被忽略
        GenericBusinessEvent businessEvent = new GenericBusinessEvent(eventPublisher.getCtx());
        businessEvent.setMessage("eventPublisher 发送 GenericBusinessEvent ");
        businessEvent.setSourceType(EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_1);
        eventPublisher.sendMessage(businessEvent);

        //发送其他业务事件 && 被忽略
        GenericBusinessEvent businessEvent2 = new GenericBusinessEvent(eventPublisher.getCtx());
        businessEvent2.setMessage("eventPublisher 发送 GenericBusinessEvent and has been ignored");
        businessEvent2.setSourceType(EventSourceTypeEnum.EVENT_SOURCE_TYPE_ENUM_BUSINESS_2);
        eventPublisher.sendMessage(businessEvent2);
    }
}

Test-1 日志输出:

代码语言:javascript
复制
2019-12-08 20:53:20.152  INFO 4522 --- [           main] c.e.spring.event.sender.MailSender       : MailSender 发送短信...
MailSendListener 收到一份邮件:Hello Testing

Test-2 日志输出:

代码语言:javascript
复制
2019-12-08 20:54:11.645  INFO 4533 --- [           main] c.e.spring.event.sender.MailSender       : MailSender 发送短信...
MailSendListener 收到一份邮件:Hello Testing
EventPublisher 开始发送com.example.spring.event.source.MailSendEvent
MailSendListener 收到一份邮件:Hello Testing Again!
EventPublisher 开始发送com.example.spring.event.source.BusinessEvent
BusinessEventListener 事件源org.springframework.web.context.support.GenericWebApplicationContext
BusinessEventListener 收到消息 com.example.spring.event.source.BusinessEvent eventPublisher 发送 businessEvent 

Test-3 日志输出:

代码语言:javascript
复制
2019-12-08 20:54:55.162  INFO 4550 --- [           main] c.e.spring.event.sender.MailSender       : MailSender 发送短信...
MailSendListener 收到一份邮件:Hello Testing
EventPublisher 开始发送com.example.spring.event.source.MailSendEvent
MailSendListener 收到一份邮件:Hello Testing Again!
EventPublisher 开始发送com.example.spring.event.source.BusinessEvent
BusinessEventListener 事件源org.springframework.web.context.support.GenericWebApplicationContext
BusinessEventListener 收到消息 com.example.spring.event.source.BusinessEventeventPublisher 发送 businessEvent 
EventPublisher 开始发送com.example.spring.event.source.BusinessEvent
BusinessEventListener 忽略消息com.example.spring.event.source.BusinessEvent eventPublisher 发送 businessEvent and has been ignored

Test-4 日志输出:

代码语言:javascript
复制
2019-12-08 20:55:30.584  INFO 4574 --- [           main] c.e.spring.event.sender.MailSender       : MailSender 发送短信...
MailSendListener 收到一份邮件:Hello Testing
EventPublisher 开始发送com.example.spring.event.source.MailSendEvent
MailSendListener 收到一份邮件:Hello Testing Again!
EventPublisher 开始发送com.example.spring.event.source.GenericBusinessEvent
BusinessGenericEventListener 事件源org.springframework.web.context.support.GenericWebApplicationContext
BusinessGenericEventListener 收到消息 com.example.spring.event.source.GenericBusinessEventeventPublisher 发送 GenericBusinessEvent 
EventPublisher 开始发送com.example.spring.event.source.GenericBusinessEvent
BusinessGenericEventListener 忽略消息com.example.spring.event.source.GenericBusinessEvent eventPublisher 发送 GenericBusinessEvent and has been ignored

总结

我们可以通过Spring自带的事件机制在项目中完成内部消息的发送和监听,实现业务模块间的解耦。本文主要介绍了Spring容器事件的使用方式,并提供了ApplicationListener的两个增强子类的使用比对和差异分析。大致主要内容有:

  • 简单使用:MailSender
  • 事件源抽象定义,实现业务事件源BusinessEvent、GenericBusinessEvent
  • 定义业务消息发送器 EventPublisher
  • 根据自定义枚举EventSourceTypeEnum做事件处理逻辑的二次分发
  • 区分GenericApplicationListener、SmartApplicationListener、ApplicationListener分别提供使用范例,并分析区别

项目结构

在这里插入图片描述

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构探险之道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • [Spring] Spring 容器事件
    • 事件体系
      • 设计结构
        • 代码实战
          • 总结
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档