Spring原理解析 之扩展原理-ApplicationListener

简介

 * 3、ApplicationListener:监听容器中发布的事件。事件驱动模型开发;
 * 	  public interface ApplicationListener<E extends ApplicationEvent>
 * 		监听 ApplicationEvent 及其下面的子事件;
 * 
 * 	 步骤:
 * 		1)、写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)
 * 			@EventListener;
 * 			原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;
 * 
 * 		2)、把监听器加入到容器;
 * 		3)、只要容器中有相关事件的发布,我们就能监听到这个事件;
 * 				ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件;
 * 				ContextClosedEvent:关闭容器会发布这个事件;
 * 		4)、发布一个事件:
 * 				applicationContext.publishEvent();

案例

创建一个自定义事件监听器类。

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {

    //当容器中发布此事件以后,方法触发
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("收到事件:"+event);
    }
}

测试类,并发布一个事件。

@Test
public void test(){
    AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(SpringConfig.class);
    //发布事件;
    applicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件")) {
    });
    applicationContext.close();
}

输出结果

收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Sun Sep 15 16:28:36 CST 2019]; root of context hierarchy]
收到事件:com.demo.IOCTest$1[source=我发布的事件]
收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Sun Sep 15 16:28:36 CST 2019]; root of context hierarchy]

ApplicationListener简介

依赖于Spring框架,在Spring启动时调用。在普通Spring应用中一般监听ContextRefreshedEvent事件。

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

同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。

需要注意的是,在普通Spring环境中,基于ApplicationListener的监听器的onApplicationEvent方法可能会被执行多次,所以需要添加以下判断:

public void onApplicationEvent(ContextRefreshedEvent event) {
    //root application context 没有parent
    if(event.getApplicationContext().getParent() == null){
    
    }
}

Spring的事件

ApplicationEvent:事件本身 事件接口。
ApplicationListener:事件监听者 事件监听器接口,所有的监听器都实现该接口。
ApplicationEventPublisher:事件发布者 事件发布接口,ApplicationContext实现了该接口。
ApplicationEventMulticaster: Spring事件机制中的事件广播器,执行事件。

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

Spring默认启动事件

  • ContextRefreshedEvent:ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 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处理用户请求结束后,系统会自动触发该事件。

SpringBoot默认启动事件

  • ApplicationStartingEvent: SpringBoot启动开始的时候执行的事件
  • ApplicationEnvironmentPreparedEvent: SpringBoot对应Enviroment已经准备完毕,但此时上下文context还没有创建。在该监听中获取到ConfigurableEnvironment后可以对配置信息做操作,例如:修改默认的配置信息,增加额外的配置信息等等。
  • ApplicationPreparedEvent: SpringBoot上下文context创建完成,但此时Spring中的bean是没有完全加载完成的。在获取完上下文后,可以将上下文传递出去做一些额外的操作。值得注意的是:在该监听器中是无法获取自定义bean并进行操作的。
  • ApplicationReadyEvent: SpringBoot加载完成时候执行的事件。
  • ApplicationFailedEvent: SpringBoot启动异常时执行事件。

Spring环境下的实现事件发布监听的方法

自定义事件,继承自ApplicationEvent抽象类。

@Getter
@Setter
public class MyApplicationEvent extends ApplicationEvent {

    private String msg;

    public MyApplicationEvent(Object source, String msg) {
        super(source);
        this.msg = msg;
    }

}

自定义监听事件的发布:

@Resource
private ApplicationContext applicationContext;
applicationContext.publishEvent(new MyApplicationEvent("测试事件", msg));

SpringBoot进行事件监听有四种方式:
1、写代码向ApplicationContext中添加监听器\

// 实现ApplicationListener接口
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

    @Override
    public void onApplicationEvent(MyApplicationEvent myApplicationEvent) {
        System.out.println("监听到事件源:" + myApplicationEvent);
    }
}

// 装载监听
@SpringBootApplication
public class MqProviderApplication {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MqProviderApplication.class);
        app.addListeners(new MyApplicationListener());//加入自定义的监听类
        app.run(args);
    }

}

2、使用Component注解将监听器装载入Spring容器

@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

    @Override
    public void onApplicationEvent(MyApplicationEvent myApplicationEvent) {
        System.out.println("监听到事件源:" + myApplicationEvent);
    }
}

3、在application.yml中配置监听器

public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
    @Override
    public void onApplicationEvent(MyApplicationEvent myApplicationEvent) {
        System.out.println("监听到事件源:" + myApplicationEvent);
    }
}
context:
  listener:
    classes: com.provider.listener.MyApplicationListener

4、通过@EventListener注解实现事件监听

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener {

    @EventListener(classes = MyApplicationEvent.class)
    public void onApplicationEvent(MyApplicationEvent myApplicationEvent) {
        System.out.println("监听到事件源:" + myApplicationEvent);
    }
}

参考:
理解 Spring ApplicationListener
Spring监听器之ApplicationListener原理及源码解析及实例

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值