• Spring Boot实践——事件监听


    借鉴:https://blog.csdn.net/Harry_ZH_Wang/article/details/79691994

       https://blog.csdn.net/ignorewho/article/details/80702827

          https://www.jianshu.com/p/edd4cb960da7

    事件监听介绍

      Spring提供5种标准的事件监听:

    1. 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext接口中的refresh()方法时被触发。
    2. 上下文开始事件(ContextStartedEvent):当容器ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
    3. 上下文停止事件(ContextStoppedEvent):当容ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
    4. 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
    5. 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。

      Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:

    1. ApplicationStartedEvent :spring boot启动开始时执行的事件
    2. ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
    3. ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
    4. ApplicationFailedEvent:spring boot启动异常时执行事件

    事件监听实现

    一、Spring Boot提供的四种事件

      1、事件监听器

      不多说,直接上代码

      ApplicationStartedEvent事件

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.context.event.ApplicationStartedEvent;
    import org.springframework.context.ApplicationListener;
    
    /**
     * Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:
     * ApplicationStartedEvent :spring boot启动开始时执行的事件
     * ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
     * ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
     * ApplicationFailedEvent:spring boot启动异常时执行事件
     * @ClassName: CustomApplicationListenerStarted 
     * @author OnlyMate
     * @Date 2018年9月14日 下午4:22:43  
     *
     */
    public class CustomApplicationListenerStarted implements ApplicationListener<ApplicationStartedEvent> {
        private Logger logger = LoggerFactory.getLogger(CustomApplicationListenerEnvironmentPrepared.class);
        
        @Override
        public void onApplicationEvent(ApplicationStartedEvent event) {
            logger.info("CustomApplicationListenerStarted ==> onApplicationEvent method");
        }
    
    }

    ApplicationEnvironmentPreparedEvent事件

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
    import org.springframework.context.ApplicationListener;
    
    /**
     * Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:
     * ApplicationStartedEvent :spring boot启动开始时执行的事件
     * ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
     * ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
     * ApplicationFailedEvent:spring boot启动异常时执行事件
     * @ClassName: CustomApplicationListenerEnvironmentPrepared 
     * @author OnlyMate
     * @Date 2018年9月14日 下午4:22:43  
     *
     */
    public class CustomApplicationListenerEnvironmentPrepared implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
        private Logger logger = LoggerFactory.getLogger(CustomApplicationListenerEnvironmentPrepared.class);
        
        @Override
        public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
            logger.info("CustomApplicationListenerEnvironmentPrepared ==> onApplicationEvent method : {}", getClass().getSimpleName());
        }

    ApplicationPreparedEvent事件

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.context.event.ApplicationPreparedEvent;
    import org.springframework.context.ApplicationListener;
    
    /**
     * Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:
     * ApplicationStartedEvent :spring boot启动开始时执行的事件
     * ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
     * ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
     * ApplicationFailedEvent:spring boot启动异常时执行事件
     * @ClassName: CustomApplicationListenerPrepared 
     * @author OnlyMate
     * @Date 2018年9月14日 下午4:22:43  
     *
     */
    public class CustomApplicationListenerPrepared implements ApplicationListener<ApplicationPreparedEvent> {
        private Logger logger = LoggerFactory.getLogger(CustomApplicationListenerEnvironmentPrepared.class);
        
        @Override
        public void onApplicationEvent(ApplicationPreparedEvent event) {
            logger.info("CustomApplicationListenerPrepared ==> onApplicationEvent method : {}", getClass().getSimpleName());
        }
    
    }

    ApplicationFailedEvent事件

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.context.event.ApplicationFailedEvent;
    import org.springframework.context.ApplicationListener;
    
    /**
     * Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:
     * ApplicationStartedEvent :spring boot启动开始时执行的事件
     * ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
     * ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
     * ApplicationFailedEvent:spring boot启动异常时执行事件
     * @ClassName: CustomApplicationListenerFailed 
     * @author OnlyMate
     * @Date 2018年9月14日 下午4:22:43  
     *
     */
    public class CustomApplicationListenerFailed implements ApplicationListener<ApplicationFailedEvent> {
        private Logger logger = LoggerFactory.getLogger(CustomApplicationListenerEnvironmentPrepared.class);
        
        @Override
        public void onApplicationEvent(ApplicationFailedEvent event) {
            logger.info("CustomApplicationListenerFailed ==> onApplicationEvent method : {}", getClass().getSimpleName());
        }
    
    }

      2、注册事件监听器

    import java.util.HashSet;
    import java.util.Set;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ConfigurableApplicationContext;
    
    import com.only.mate.springboot.listener.original.CustomApplicationListenerEnvironmentPrepared;
    import com.only.mate.springboot.listener.original.CustomApplicationListenerFailed;
    import com.only.mate.springboot.listener.original.CustomApplicationListenerPrepared;
    import com.only.mate.springboot.listener.original.CustomApplicationListenerStarted;
    
    
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
    //使用 @EnableWebMvc 注解,需要以编程的方式指定视图文件相关配置;
    //@EnableWebMvc
    //使用 @EnableAutoConfiguration 注解,会读取 application.properties 或 application.yml 文件中的配置
    @EnableAutoConfiguration
    @ServletComponentScan//springboot启动类扫描servlet组件(过滤器)
    public class Application {
        public static ApplicationContext applicationContext;
        
        private static final Logger logger = LoggerFactory.getLogger(Application.class);
    
        public static void main(String[] args) {
            startApplication(args);
        }
    
        public static ApplicationContext startApplication(String[] args) {
            if (applicationContext == null) {
                logger.info(" >>> Springboot Application 开始启动...");
                SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
                SpringApplication application = builder.application();
                application.addListeners(new CustomApplicationListenerEnvironmentPrepared());//这里注册事件监听器
                application.addListeners(new CustomApplicationListenerFailed());//这里注册事件监听器
                application.addListeners(new CustomApplicationListenerPrepared());//这里注册事件监听器
                application.addListeners(new CustomApplicationListenerStarted());//这里注册事件监听器
                
                applicationContext = application.run(args);
                logger.info(" >>> Springboot Application 启动完成!");
            }
            return applicationContext;
        }
        
        public static ApplicationContext getApplicationContext() {
            if (applicationContext == null) {
                logger.error(" >>> Error:Springboot Application ApplicationContext is Null.");
            }
            return applicationContext;
        }
    
    }

    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
    //使用 @EnableWebMvc 注解,需要以编程的方式指定视图文件相关配置;
    //@EnableWebMvc
    //使用 @EnableAutoConfiguration 注解,会读取 application.properties 或 application.yml 文件中的配置
    @EnableAutoConfiguration
    @ServletComponentScan//springboot启动类扫描servlet组件(过滤器)
    public class Application {
        public static ApplicationContext applicationContext;
        
        private static final Logger logger = LoggerFactory.getLogger(Application.class);
    
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(Application.class);
            application.addListeners(new CustomApplicationListenerEnvironmentPrepared());//这里注册事件监听器
            application.addListeners(new CustomApplicationListenerFailed());//这里注册事件监听器
            application.addListeners(new CustomApplicationListenerPrepared());//这里注册事件监听器
            application.addListeners(new CustomApplicationListenerStarted());//这里注册事件监听器
            application.run(args);
        }
    }

    注意:注册事件监听器一定要在启动之前注册。

      3、效果图

    启动成功是只有三个事件被监听到的。

    二、自定义事件监听

      Spring的事件遵循的流程:

    1. 自定义事件,继承ApplicationEvent(org.springframework.context.ApplicationEvent)
    2. 自定义监听,实现ApplicationListener<T>(org.springframework.context.ApplicationListener)接口,然后实现onApplicationEvent方法
    3. 使用容器触发事件

      1、自定义事件

    /**
     * @Description: 自定义事件 
     * @ClassName: CustomEvent 
     * @author OnlyMate
     * @Date 2018年9月14日 下午3:01:58  
     *
     */
    public class CustomEvent extends ApplicationEvent {
        
        private static final long serialVersionUID = -7058371859589691525L;
        private Logger logger = LoggerFactory.getLogger(CustomEvent.class);    
        
        private String msg;
        
        public CustomEvent(Object source,String msg) {
            super(source);
            this.msg = msg;
        }
    
        /**
         * 自定义监听器触发的透传打印方法
         * @Title: printMsg 
         * @author OnlyMate
         * @Date 2018年9月14日 下午3:10:45 
         * @param msg
         */
        public void printMsg(String msg) {
            logger.info("CustomEvent ==> printMsg method 自定义事件: {}", msg);
        }
        
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
    }

      2、自定义事件发布

    import javax.annotation.Resource;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.stereotype.Service;
    
    /**
     * 发布消息服务
     * @ClassName: CustomListenerServie 
     * @author OnlyMate
     * @Date 2018年9月14日 下午3:18:46  
     *
     */
    @Service(value="customListenerServie")
    public class CustomListenerServie {
        private Logger logger = LoggerFactory.getLogger(CustomListenerServie.class);    
        
        //上下文对象
        @Resource
        private ApplicationContext applicationContext;
    
        /**
         * 发布消息
         * @Title: publish 
         * @author OnlyMate
         * @Date 2018年9月14日 下午3:18:35 
         * @param msg
         */
        public void publish(String msg) {
            //通过上下文对象发布监听
            applicationContext.publishEvent(new CustomEvent(this,msg));
            logger.info("CustomListenerServie ==> publish method : {}", msg);
        }
    }

      3、触发自定义事件

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.only.mate.springboot.listener.CustomListenerServie;
    
    @Controller
    @RequestMapping(value="/listener")
    public class CustomListenerController {
        @Autowired
        @Qualifier(value = "customListenerServie")
        private CustomListenerServie customListenerServie;
    
        @ResponseBody
        @RequestMapping(value="/testevent")
        public String testEvent() {
            customListenerServie.publish("测试监听");
            return "success";
        }
    }

      4、自定义事件监听器并注册事件监听器

      Spring Boot进行事件监听有四种方式:

    1. 手工向ApplicationContext中添加监听器
    2. 在application.properties中配置监听器
    3. 将监听器装载入Spring容器
    4. 通过@EventListener注解实现事件监听

      a、手工向ApplicationContext中添加监听器

      事件监听器
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.ApplicationListener;
    
    /**
     * 自定义监听器,监听事件为CustomEvent
     * @ClassName: CustomListener 
     * @author OnlyMate
     * @Date 2018年9月14日 下午3:13:43  
     *
     */
    public class CustomListener implements ApplicationListener<CustomEvent>{
        private Logger logger = LoggerFactory.getLogger(CustomAnnotationListener.class);    
        /**
         * 对监听到的事件进行处理
         */
        @Override
        public void onApplicationEvent(CustomEvent event) {
            //这里不做处理,只对消息进行透传打印,实际情况,
            //可以根据项目进行逻辑进行处理
            event.printMsg(event.getMsg());
            logger.info("CustomListener ==> onApplicationEvent method : {}", event.getMsg());
        }
    
    }
      配置
    import java.util.HashSet;
    import java.util.Set;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ConfigurableApplicationContext;
    
    import com.only.mate.springboot.listener.CustomListener;
    
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
    //使用 @EnableWebMvc 注解,需要以编程的方式指定视图文件相关配置;
    //@EnableWebMvc
    //使用 @EnableAutoConfiguration 注解,会读取 application.properties 或 application.yml 文件中的配置
    @EnableAutoConfiguration
    @ServletComponentScan//springboot启动类扫描servlet组件(过滤器)
    public class Application {
        public static ApplicationContext applicationContext;
        
        private static final Logger logger = LoggerFactory.getLogger(Application.class);
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
            context.addApplicationListener(new CustomListener());//这里注册事件监听器
        }
    }

      或

    import java.util.HashSet;
    import java.util.Set;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    import org.springframework.context.ApplicationContext;
    
    import com.only.mate.springboot.listener.CustomListener;
    
    
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
    //使用 @EnableWebMvc 注解,需要以编程的方式指定视图文件相关配置;
    //@EnableWebMvc
    //使用 @EnableAutoConfiguration 注解,会读取 application.properties 或 application.yml 文件中的配置
    @EnableAutoConfiguration
    @ServletComponentScan//springboot启动类扫描servlet组件(过滤器)
    public class Application {
        public static ApplicationContext applicationContext;
        
        private static final Logger logger = LoggerFactory.getLogger(Application.class);
    
        public static void main(String[] args) {
            startApplication(args);
        }
    
        public static ApplicationContext startApplication(String[] args) {
            if (applicationContext == null) {
                logger.info(" >>> Springboot Application 开始启动...");
                SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
                SpringApplication application = builder.application();
                application.addListeners(new CustomListener());//这里注册事件监听器
                applicationContext = application.run(args);
                logger.info(" >>> Springboot Application 启动完成!");
            }
            return applicationContext;
        }
        
        public static ApplicationContext getApplicationContext() {
            if (applicationContext == null) {
                logger.error(" >>> Error:Springboot Application ApplicationContext is Null.");
            }
            return applicationContext;
        }
    
    }
      效果图

      访问http://localhost:8088/springboot/listener/testevent

      b、在application.properties中配置监听器

      事件监听器
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.ApplicationListener;
    
    /**
     * 自定义监听器,监听事件为CustomEvent
     * @ClassName: CustomListener 
     * @author OnlyMate
     * @Date 2018年9月14日 下午3:13:43  
     *
     */
    public class CustomListener implements ApplicationListener<CustomEvent>{
        private Logger logger = LoggerFactory.getLogger(CustomAnnotationListener.class);    
        /**
         * 对监听到的事件进行处理
         */
        @Override
        public void onApplicationEvent(CustomEvent event) {
            //这里不做处理,只对消息进行透传打印,实际情况,
            //可以根据项目进行逻辑进行处理
            event.printMsg(event.getMsg());
            logger.info("CustomListener ==> onApplicationEvent method : {}", event.getMsg());
        }
    
    }
      配置

      在application.properties中配置监听

    context.listener.classes=com.only.mate.springboot.listener.CustomListener
      效果图

      访问http://localhost:8088/springboot/listener/testevent

      c、将监听器装载入Spring容器

      事件监听器
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.ApplicationListener;
    import org.springframework.stereotype.Component;
    
    /**
     * 自定义监听器,监听事件为CustomEvent
     * @ClassName: CustomListener 
     * @author OnlyMate
     * @Date 2018年9月14日 下午3:13:43  
     *
     */
    @Component
    public class CustomListener implements ApplicationListener<CustomEvent>{
        private Logger logger = LoggerFactory.getLogger(CustomAnnotationListener.class);    
        /**
         * 对监听到的事件进行处理
         */
        @Override
        public void onApplicationEvent(CustomEvent event) {
            //这里不做处理,只对消息进行透传打印,实际情况,
            //可以根据项目进行逻辑进行处理
            event.printMsg(event.getMsg());
            logger.info("CustomListener ==> onApplicationEvent method : {}", event.getMsg());
        }
    
    }

    这里用@Component注解将事件监听器注册到Spring容器中

      效果图

      访问http://localhost:8088/springboot/listener/testevent

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

      事件监听器
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.event.EventListener;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CustomAnnotationListener {
        private Logger logger = LoggerFactory.getLogger(CustomAnnotationListener.class);    
        
        @EventListener
        public void listener1(CustomEvent event) {
            event.printMsg(event.getMsg());
            logger.info("CustomAnnotationListener ==> listener1 method : {}", event.getMsg());
        }
    
        @EventListener
        public void listener2(CustomEvent event) {
            event.printMsg(event.getMsg());
            logger.info("CustomAnnotationListener ==> listener2 method : {}", event.getMsg());
        }
    }
      效果图

      访问http://localhost:8088/springboot/listener/testevent


      如果是使用配置文件来注册的话,ApplicationStartedEvent这种事件是监听不到的,因为配置文件加载代表着Spring Boot已经启动,不过其他两种事件已经足够给项目上使用了。
  • 相关阅读:
    JavaScript 深度克隆 JSON 对象
    NetBeans IDE 6.7.1 with JavaFX Now Available for Download!
    NetBeans 时事通讯(刊号 # 65 Jul 21, 2009)
    来自雨林木风的Linux发行版: Ylmf Linux
    JavaScript 深度克隆 JSON 对象
    STL vector vs list function comparison:
    手把手教你把Vim改装成一个IDE编程环境(图文)
    Using Visual Leak Detector
    疯狂的编程世界_IT新闻_博客园
    分享好段子:
  • 原文地址:https://www.cnblogs.com/onlymate/p/9647995.html
Copyright © 2020-2023  润新知