Spring监听器


事件监听概念

应用程序事件允许我们发送和接收特定事件,我们可以根据需要处理这些事件。事件用于在松散耦合的组件之间交换信息。由于发布者和订阅者之间没有直接耦合,因此可以在不影响发布者的情况下修改订阅者,反之亦然。

事件监听三要素

  1. 事件源:事件对象的产生者,任何一个事件都有一个来源
    ApplicationEvent
  2. 事件监听器:事件框架或组件收到一个事件后,需要通知所有相关的事件监听器来进行处理。这些监听器统一存储在事件监听器注册表中。
    ApplicationListener(编码式事件监听器)
    @EventListener(注解式事件监听器)
  3. 发布事件:ApplicationContext(spring容器)

JDK事件

Java中,通过java.util. EventObject来描述事件,通过java.util. EventListener来描述事件监听器。

Spring事件

  1. 事件源:ApplicationEvent
  2. 事件监听器:ApplicationListener(编码式事件监听器)、@EventListener(注解式事件监听器)
  3. 发布事件:ApplicationContext(spring容器)

ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。

如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。
spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。

事件:ApplicationEvent

ApplicationEvent是Spring事件的顶层抽象类,代表事件本身,继承自JDK的EventObject。Spring提供了一些内置事件,如ContextClosedEvent、ContextStartedEvent、ContextRefreshedEvent、ContextStopedEvent等

事件类描述
ContextRefreshedEventApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用
ContextStartedEvent当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序
ContextStoppedEvent当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作
ContextClosedEvent当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
RequestHandledEvent这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。
事件监听器:ApplicationListener

ApplicationListener是Spring事件监听器顶层接口,所有的监听器都实现该接口,继承自JDK的EventListener。Spring提供了一些易扩展的接口,如SmartApplicationListener、GenericApplicationListener

事件发布:ApplicationEventPublisher

ApplicationEventPublisher是Spring的事件发布接口,事件源通过该接口的publishEvent方法发布事件,所有的应用上下文都具备事件发布能力,因为ApplicationContext继承了该接口

事件广播器:ApplicationEventMulticaster

ApplicationEventMulticaster是Spring事件机制中的事件广播器,它默认提供一个SimpleApplicationEventMulticaster实现,如果用户没有自定义广播器,则使用默认的(初始化逻辑见AbstractApplicationContext的refresh方法)。它通过父类AbstractApplicationEventMulticaster的getApplicationListeners方法从事件注册表中获取事件监听器,并且通过invokeListener方法执行监听器的具体逻辑。
默认的广播器是同步调用监听器的执行逻辑,但是可以通过为广播器配置Executor实现监听器的异步执行。

在Spring中通常是ApplicationContext本身担任监听器注册表的角色,在其子类AbstractApplicationContext中就聚合了事件广播器ApplicationEventMulticaster和事件监听器ApplicationListnener,并且提供注册监听器的addApplicationListnener方法。

当一个事件源产生事件时,它通过事件发布器ApplicationEventPublisher发布事件,然后事件广播器ApplicationEventMulticaster会去事件注册表ApplicationContext中找到事件监听器ApplicationListnener,并且逐个执行监听器的onApplicationEvent方法,从而完成事件监听器的逻辑。

SpringBoot事件

事件:SpringApplicationEvent

SpringApplicationEvent是SpringBoot事件的顶层抽象类,且SpringBoot内置了7个事件:

自定义事件监听

自定义事件监听一般包括事件源和、事件监听器

1.自定义事件源(Event):
import org.springframework.context.ApplicationEvent;

public class TestEvent extends ApplicationEvent {

    public TestEvent(Object obj) {
        super(obj);
    }
}

2.自定义事件监听器(Listener)
1.自定义监听器类+@Component
@Component
public class TestListener implements ApplicationListener<TestEvent> {
    @Override
    public void onApplicationEvent(TestEvent event) {
	    System.out.println("监听到事件发生:"+event.getClass());	
    }
}
2.自定义监听器类+addListeners()
public class TestListener implements ApplicationListener<TestEvent> {
    @Override
    public void onApplicationEvent(TestEvent event) {
	    System.out.println("监听到事件发生:"+event.getClass());
    }
}
@SpringBootApplication
public class ScheduleApplication {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(ScheduleApplication.class);
        springApplication.addListeners(new TestListener());
        springApplication.run(args);
    }
}
3.自定义监听器类+配置文件
public class TestListener implements ApplicationListener<TestEvent> {
    @Override
    public void onApplicationEvent(TestEvent event) {
	    System.out.println("监听到事件发生:"+event.getClass());
    }
}
context:
  listener:
    classes: com.test.TestListener
4.@EventListener+@Component
@Component
public class TestListener {
    @EventListener
    public void eventListener(TestEvent event) {
        System.out.println("监听到事件发生:"+event.getClass());
    }
}
3.发布事件测试
@SpringBootApplication
public class ScheduleApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ScheduleApplication.class, args);
        context.publishEvent(new TestEvent(1));
    }
}

ApplicationListener接口和SmartApplicationListener接口区别
  • 实现ApplicationListener接口针对单一事件监听

  • 实现SmartApplicationListener接口针对多种事件监听

SmartApplicationListener用法举例:

@Component
public class TestListener implements SmartApplicationListener {
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        boolean b = TestEvent.class.isAssignableFrom(eventType) || Test2Event.class.isAssignableFrom(eventType);
        return b;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("监听到事件发生:"+event.getClass());

    }
}

  1. 测试用例

    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class ListenerTest {
    
        @Autowired
        private ApplicationEventPublisher applicationEventPublisher;
    
        @Test
        public void test() {
            TestEvent testEvent = new TestEvent("hello word");
            applicationEventPublisher.publishEvent(testEvent);
        }
    }
    
    

常用监听器接口

ServletContextListener

监听servletContext对象的创建以及销毁
执行时机:

  1. contextInitialized(ServletContextEvent arg0) – 创建时执行

  2. contextDestroyed(ServletContextEvent arg0) – 销毁时执行

ServletRequestListener

监听request对象的创建以及销毁
执行时机:

  1. requestInitialized(ServletRequestEvent sre) – 创建时执行

  2. requestDestroyed(ServletRequestEvent sre) – 销毁时执行

HttpSessionListener

监听session对象的创建以及销毁
执行时机:

  1. sessionCreated(HttpSessionEvent se) – 创建时执行

  2. sessionDestroyed(HttpSessionEvent se) – 销毁时执行

ServletContextAttributeListener

监听servletContext对象中属性的改变
执行时机:

  1. attributeAdded(ServletContextAttributeEvent event) – 添加属性时执行

  2. attributeReplaced(ServletContextAttributeEvent event) – 修改属性时执行

  3. attributeRemoved(ServletContextAttributeEvent event) – 删除属性时执行

ServletRequestAttributeListener

监听request对象中属性的改变

  1. attributeAdded(ServletRequestAttributeEvent srae) – 添加属性时执行

  2. attributeReplaced(ServletRequestAttributeEvent srae) – 修改属性时执行

  3. attributeRemoved(ServletRequestAttributeEvent srae) – 删除属性时执行

HttpSessionAttributeListener

监听session对象中属性的改变

  1. attributeAdded(HttpSessionBindingEvent event) – 添加属性时执行

  2. attributeReplaced(HttpSessionBindingEvent event) – 修改属性时执行

  3. attributeRemoved(HttpSessionBindingEvent event) – 删除属性时执行

参考文章:
https://zhuanlan.zhihu.com/p/270596548

  • 10
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值