springboot之ApplicationListener


通过ApplicationContextAware我们可以把系统中所有ApplicationEvent传播给系统中所有的ApplicationListener。因此,我们只需要构造好我们自己的ApplicationEvent和ApplicationListener,就可以在系统中实现相应的监听器。

如果在上下文中部署一个实现了ApplicationListener接口的bean,那么每当在一个ApplicationEvent发布到 ApplicationContext时,这个bean得到通知。其实这就是标准的Oberver设计模式。

ApplicationListener

是一个接口,里面只有一个onApplicationEvent方法。具体的执行逻辑

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

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

}

SmartApplicationListener 接口继承了ApplicationListener,并继承了Order接口

public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
}

ApplicationEvent

是个抽象类,里面只有一个构造函数和一个长整型的timestamp。实现类可以扩充相应的属性。

使用

继承ApplicationListener

public class DemoApplicationListener implements ApplicationListener<ContextRefreshedEvent>{
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("DemoApplicationListener 被调用了。");
    }
}

通过配置类进行实例化

@Configuration
public class ListenerConfig {

    @Bean
    public ApplicationStartListener applicationStartListener(){
        return new ApplicationStartListener();
    }
}

自定义ApplicationListener

实现步骤

  1. 自定义事件:扩展ApplicationEvent类,需要有构造函数。
  2. 自定义事件监听器:实现ApplicationListener接口,重写onApplicationEvent方法,该方法处理监听到某个时间后做哪些操作。
  3. 通过ApplicationContext发布事件

Spring 提供的ApplicationEvent & Listener有3种实现方式:

  • @EventListener 注解的方式;
  • 实现ApplicationListener接口;
  • 实现SmartApplicationListener接口;

@EventListener

通过给方法添加@EventListener注解实现


@Component
public class MyApplicationListener  {
    //参数的范围越广泛,监听到的事件越多
    //如果入参是ApplicationEvent,则每当容器内发生任何事件时,此方法都会被触发
    //如果入参是MyApplicationEvent,则只有容器内发生如果入参是MyApplicationEvent事件时,此方法才会被触发
    @EventListener
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println(event.getClass().getName() + "被监听......");
        if(event instanceof MyApplicationEvent){
            MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
            System.out.println("MyApplicationEvent.msg is :"+(myApplicationEvent.getMsg()));
        }
    }
}

SmartApplicationListener

SmartApplicationListener是高级监听器,是ApplicationListener的子类,能够实现有序监听。
SmartApplicationListener接口继承了ApplicationListener 和 Ordered接口,实现了事件监听和排序的功能。

@Component
public class OrderEventListener implements SmartApplicationListener {

    /**
     * 支持的事件类型
     *
     * @param eventType
     * @return
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == OrderStatusMsgEvent.class;
    }

    /**
     * 事件发生的目标类
     *
     * @param sourceType 事件发生的目标类类型
     * @return
     */
    @Override
    public boolean supportsSourceType(@Nullable Class<?> sourceType) {
        return true;
    }

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

    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        // 获取注册用户信息
        OrderStatusMsgEvent orderStatusMsgEvent = (OrderStatusMsgEvent) applicationEvent;
        OrderDTO orderInfo = orderStatusMsgEvent.getOrderDTO();

        // 模拟kafka发送
        // kafkaProducer.sendMsg(orderInfo);
        System.out.println("======kafka发送成功====");

    }
}

支持异步

onApplicationEvent上增加 @Async 即可

@Override
    @Async
    public void onApplicationEvent(ApplicationEvent applicationEvent)

自定义ApplicationEvent

上例中的ContextRefreshedEvent会在Spring容器初始化完成会触发该事件。我们也可以自定义ApplicationEvent。

public class DemoApplicationEvent extends ApplicationEvent{
   //设置一系列的属性
}

触发自定义的ApplicationEvent

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
DemoApplicationEvent event = new DemoApplicationEvent ();
     //主动触发该事件
context.publishEvent(event);

内置的ApplicationEvent

内置事件描述
ContextRefreshedEventpplicationContext 被初始化或刷新时,该事件被发布。
ContextStartedEvent当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。
ContextStoppedEvent当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。
ContextClosedEvent当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。
RequestHandledEvent这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。

内置的ApplicationListener

在 SpringApplication 构造方法中,会调用 #getSpringFactoriesInstances(Class type) 方法,获得 ApplicationListener 集合。这个利用的还是Factories机制。spring.factories文件的定义如下

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

ConfigFileApplicationListener实现 SmartApplicationListener、Ordered、EnvironmentPostProcessor 接口,实现 Spring Boot 配置文件的加载。
AnsiOutputApplicationListener 现 ApplicationListener、Ordered 接口,在 Spring Boot 环境变量(environment)准备完成以后运行。
GenericApplicationListener 实现根据配置初始化日志系统 Logger 。
ClasspathLoggingApplicationListener ,实现 GenericApplicationListener 接口,程序启动时,将 classpath 打印到 debug 日志,启动失败时 classpath 打印到 debug 日志。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值