首页 > 编程语言 > 详细

spring-boot-learning-监听事件

时间:2020-09-01 16:30:03      阅读:101      评论:0      收藏:0      [点我收藏+]

 

Springboot扩展了Spring的ApplicatoionContextEvent,提供了事件:

 

ApplicationStartingEvent:框架启动事件

ApplicationEnvironmentPreparedEvent: springboot 对应Evironment已经准备完毕了,但是上下文还没有创建。

ApplicationContextInitializedEvent:  上下文初始化

ApplicationPreparedEvent:    springboot 上下文context创建完成,但是bean没有完全加载

ApplicationStartedEvent:   springboot 启动开始执行的事件

ApplicationReadyEvent :   调用Runners接口完毕

ApplicationFailedEvent:启动异常执行事件

技术分享图片

 

 

 

 

 * springboot自带的事件。
 * ApplicationStartingEvent
 * Spring Application启动事件。事件产生的时机为ApplicationListeners注册之后,Environment或ApplicationContext可用之前,
    事件源为Spring Application自身,ApplicationStartingEvent在生命周期过程中可能会被修改,请谨慎使用。
* ApplicationEnvironmentPreparedEvent * 事件产生的时机为Spring Application已经启动,Environment第一次可用。
* ApplicationPreparedEvent * 事件产生的时机为Spring Application已经启动,Application Context已经完全准备好但是还没有进行刷新,在该阶段已经开始加载Bean定义并且Environment已经完全可用。
* ApplicationStartedEvent * 事件产生的时机为Application Context已经完成刷新,ApplicationRunner application和CommandLineRunner调用之前。
* ApplicationReadyEvent * Spring Application已经准备好对外提供服务。
* ApplicationFailedEvent * 应用启动失败

 

自定义监听器的步骤:

1,建立监听类继承ApplicationListener

2, 继承方法onApplicationEvent

3, 在resource建立文件夹/META-INF/spring.factories

4, 文件里写入:

org.springframework.context.ApplicationListener=com.quan.sbrabbit.Listener.QuanListenerEnvPreparedEvent ,com.quan.sbrabbit.Listener.QuanListenerStartedEvent,com.quan.sbrabbit.Listener.QuanListenerPreparedEvent

 

 

/**
 * spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。在该监听中获取到ConfigurableEnvironment
 * 后可以对配置信息做操作,例如:修改默认的配置信息
 */

public class QuanListenerEnvPreparedEvent implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        ConfigurableEnvironment environment = event.getEnvironment();
        MutablePropertySources sources =environment.getPropertySources();
        if (sources != null){
            Iterator<PropertySource<?>> iterator = sources.iterator();
            while (iterator.hasNext()){
                PropertySource<?> propertySource = iterator.next();
                System.out.println(propertySource.getName());
                System.out.println(propertySource.getSource());
                System.out.println(propertySource.getClass());
            }
            System.out.println("监听到ApplicationEnvironmentPreparedEvent");
//            for (PropertySource<?> p :
//                    sources) {
//                System.out.println(p.getName());
//                System.out.println(p.getSource());
//                System.out.println(p.getClass());
//            }
        }
    }
}

 

 

/**
 * pring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
 * 在获取完上下文后,可以将上下文传递出去做一些额外的操作。
 * 值得注意的是:在该监听器中是无法获取自定义bean并进行操作的。
 */
public class QuanListenerPreparedEvent implements ApplicationListener<ApplicationPreparedEvent> {
    @Override
    public void onApplicationEvent(ApplicationPreparedEvent event) {
        ConfigurableApplicationContext context = event.getApplicationContext();
        context.toString();
        System.out.println("监听到ApplicationPreparedEvent");
    }
}

 

public class QuanListenerStartedEvent implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        SpringApplication application = event.getSpringApplication();
        System.out.println(application);
        //控制台或日志中会默认显示一个Banner,关闭这个东西
        application.setBannerMode(Banner.Mode.OFF);
        System.out.println("监听到applicationStartedEvent");
    }
}

 

加入:

org.springframework.context.ApplicationListener=com.quan.sbrabbit.Listener.QuanListenerEnvPreparedEvent ,com.quan.sbrabbit.Listener.QuanListenerStartedEvent,com.quan.sbrabbit.Listener.QuanListenerPreparedEvent

 

运行输出:

监听到ApplicationEnvironmentPreparedEvent

  .   ____          _            __ _ _
 /\\ / ___‘_ __ _ _(_)_ __  __ _ \ \ \ ( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
    |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.3.RELEASE)

2020-09-01 14:10:32.063  WARN 99192 --- [           main] o.s.boot.StartupInfoLogger               : InetAddress.getLocalHost().getHostName() took 5004 milliseconds to respond. Please verify your network configuration (macOS machines may need to add entries to /etc/hosts).
2020-09-01 14:10:37.067  INFO 99192 --- [           main] com.quan.sbrabbit.SbrabbitApplication    : Starting SbrabbitApplication on quandeMacBook-Pro.local with PID 99192 (/Users/quan/Desktop/ALLLL/sbrabbit/target/classes started by quan in /Users/quan/Desktop/ALLLL/sbrabbit)
2020-09-01 14:10:37.068  INFO 99192 --- [           main] com.quan.sbrabbit.SbrabbitApplication    : No active profile set, falling back to default profiles: default
监听到ApplicationPreparedEvent
2020-09-01 14:10:37.491  INFO 99192 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2020-09-01 14:10:37.505  INFO 99192 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 11ms. Found 0 Elasticsearch repository interfaces.
2020-09-01 14:10:37.509  INFO 99192 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
2020-09-01 14:10:37.511  INFO 99192 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 2ms. Found 0 Reactive Elasticsearch repository interfaces.
2020-09-01 14:10:37.762  INFO 99192 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9898 (http)
2020-09-01 14:10:37.768  INFO 99192 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-09-01 14:10:37.769  INFO 99192 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.37]
2020-09-01 14:10:37.838  INFO 99192 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-09-01 14:10:37.839  INFO 99192 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 740 ms
2020-09-01 14:10:38.006  INFO 99192 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService ‘applicationTaskExecutor‘
2020-09-01 14:10:38.502  WARN 99192 --- [           main] o.s.data.convert.CustomConversions       : Registering converter from class org.springframework.data.geo.Point to interface java.util.Map as writing converter although it doesn‘t convert to a store-supported type! You might want to check your annotation setup at the converter implementation.
2020-09-01 14:10:38.502  WARN 99192 --- [           main] o.s.data.convert.CustomConversions       : Registering converter from interface java.util.Map to class org.springframework.data.geo.Point as reading converter although it doesn‘t convert from a store-supported type! You might want to check your annotation setup at the converter implementation.
2020-09-01 14:10:38.503  WARN 99192 --- [           main] o.s.data.convert.CustomConversions       : Registering converter from class org.springframework.data.elasticsearch.core.geo.GeoPoint to interface java.util.Map as writing converter although it doesn‘t convert to a store-supported type! You might want to check your annotation setup at the converter implementation.
2020-09-01 14:10:38.503  WARN 99192 --- [           main] o.s.data.convert.CustomConversions       : Registering converter from interface java.util.Map to class org.springframework.data.elasticsearch.core.geo.GeoPoint as reading converter although it doesn‘t convert from a store-supported type! You might want to check your annotation setup at the converter implementation.
2020-09-01 14:10:38.604  INFO 99192 --- [           main] o.s.d.elasticsearch.support.VersionInfo  : Version Spring Data Elasticsearch: 4.0.3.RELEASE
2020-09-01 14:10:38.604  INFO 99192 --- [           main] o.s.d.elasticsearch.support.VersionInfo  : Version Elasticsearch Client in build: 7.6.2
2020-09-01 14:10:38.605  INFO 99192 --- [           main] o.s.d.elasticsearch.support.VersionInfo  : Version Elasticsearch Client used: 7.6.2
2020-09-01 14:10:38.605  INFO 99192 --- [           main] o.s.d.elasticsearch.support.VersionInfo  : Version Elasticsearch cluster: 6.8.4
2020-09-01 14:10:38.605  WARN 99192 --- [           main] o.s.d.elasticsearch.support.VersionInfo  : Version mismatch in between Elasticsearch Client and Cluster: 7.6.2 - 6.8.4
2020-09-01 14:10:38.688  INFO 99192 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9898 (http) with context path ‘‘
2020-09-01 14:10:38.698  INFO 99192 --- [           main] com.quan.sbrabbit.SbrabbitApplication    : Started SbrabbitApplication in 16.941 seconds (JVM running for 22.495)
org.springframework.boot.SpringApplication@4a163575
监听到applicationStartedEvent

 

 

自定义事件:必须继承抽象类ApplicationEvent

public class QuanEvent extends ApplicationEvent {


    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public QuanEvent(String source) {
        super(source);
        System.out.println("事件  "+source);
    }
}

 

自定义监听器:监听自己定义的事件

public class QuanListenerQuanEvent implements ApplicationListener<QuanEvent> {
    @Override
    public void onApplicationEvent(QuanEvent event) {
        System.out.println("监听到QuanEvent");

    }
}

 

在完成springboot启动事件ApplicationStaredEvent中发布事件:

public class QuanListenerStartedEvent implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        event.getApplicationContext().publishEvent(new QuanEvent("hello"));
    }
}

 

最后加上监听器的配置:
在spring.factories追加:

,com.quan.sbrabbit.Listener.QuanListenerQuanEvent

运行结果:

技术分享图片

 

 

也可以使用注解进行监听器的编写(这时候只需要将监听器加载到bean容器里面就行,)

使用注解@EventListener

@Component
public class QuanListenerQuanEvent  {
    @EventListener
    public void onApplicationEvent(QuanEvent event) {
        System.out.println("监听到QuanEvent");

    }
}

 

 

监听事件的原理:

 

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

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

}

 

监听器触发机制:

技术分享图片

 

 

SpringApplication-run 方法
public ConfigurableApplicationContext run(String... args){
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
}
进入starting方法到SpringApplicationRunListener类
    void starting() {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.starting();
        }
    }
    遍历所有的SpringApplicationRunListener

再进入starting:来到EventPublishingRunListener类:
    @Override
    public void starting() {
        this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    }
调用广播器发送



进入multicastEvent方法属于这个类:SimpleApplicationEventMulticaster
@Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        Executor executor = getTaskExecutor(); //获得线程池
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {//获取对当前event感兴趣的监听器列表
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                invokeListener(listener, event);
            }
        }
    }


进入getApplicationListeners方法到类AbstractApplicationEventMulticaster
protected Collection<ApplicationListener<?>> getApplicationListeners(
            ApplicationEvent event, ResolvableType eventType) {

        Object source = event.getSource();//获得事件来源


其实source就是SpringApplication

 

 

 

技术分享图片

 

spring-boot-learning-监听事件

原文:https://www.cnblogs.com/java-quan/p/13588285.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!