借鉴: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种标准的事件监听:
- 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:
- ApplicationStartedEvent :spring boot启动开始时执行的事件
- ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
- ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
- 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的事件遵循的流程:
- 自定义事件,继承ApplicationEvent(org.springframework.context.ApplicationEvent)
- 自定义监听,实现ApplicationListener<T>(org.springframework.context.ApplicationListener)接口,然后实现onApplicationEvent方法
- 使用容器触发事件
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进行事件监听有四种方式:
- 手工向ApplicationContext中添加监听器
- 在application.properties中配置监听器
- 将监听器装载入Spring容器
- 通过@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已经启动,不过其他两种事件已经足够给项目上使用了。