009-Spring Boot 事件监听、监听器配置与方式、spring、Spring boot内置事件
一、概念
1.事件监听的流程
步骤一、自定义事件,一般是继承ApplicationEvent抽象类
步骤二、定义事件监听器,一般是实现ApplicationListener接口
步骤三、启动时,需要将监听器加入到Spring容器中
步骤四、发布事件
对于配置监听器的方式【即第三步】
方式一、app.addListeners(new MyApplicationListener());添加监听器
方式二、把监听器使用纳入Spring配置中管理如使用@Component标注
方式三、再application.properties中添加context.listener.classes配置项配置
方式四、使用注解@EventListener在方法上,且该类需要在Spring上管理
2、示例【方式一】:
步骤一、自定义事件MyApplicationEvent
package com.lhx.spring.springboot_event; import org.springframework.context.ApplicationEvent; /**
* 定义事件
* @author Administrator
*
*/
public class MyApplicationEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L; public MyApplicationEvent(Object source) {
super(source);
}
}
步骤二、定义事件监听器MyApplicationListener
package com.lhx.spring.springboot_event;
import org.springframework.context.ApplicationListener;
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
@Override
public void onApplicationEvent(MyApplicationEvent event) {
System.out.println("接收到事件:" + event.getClass());
}
}
步骤三、在App启动程序中添加以及发布
@SpringBootApplication
public class App {
public static void main(String[] args) {
// ConfigurableApplicationContext context = SpringApplication.run(App.class,
// args);
SpringApplication app = new SpringApplication(App.class);
app.addListeners(new MyApplicationListener());
ConfigurableApplicationContext context = app.run(args);
context.publishEvent(new MyApplicationEvent(new Object()));
context.close();
}
}
3、示例【方式二】:
注意:其实在示例步骤三,也可以用注解方式将时间监听器纳入Spring管理中
步骤一、与示例一一致
步骤二、将事件监听器添加@Component注解。
步骤三、启动类
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(App.class);
//app.addListeners(new MyApplicationListener());
ConfigurableApplicationContext context = app.run(args);
context.publishEvent(new MyApplicationEvent(new Object()));
context.close();
}
}
4、示例【方式四】:
步骤一、与示例一一致
步骤二、与示例一一致
步骤三、增加单独处理类
package com.lhx.spring.springboot_event; import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component; @Component
public class MyEventHandle {
@EventListener
public void event(MyApplicationEvent event) {
System.out.println("MyEventHandle 接收到事件:" + event.getClass());
} @EventListener
public void event2(ContextStoppedEvent event) {
System.out.println("应用停止 接收到事件:" + event.getClass());
}
}
步骤三、启动类
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(App.class);、
ConfigurableApplicationContext context = app.run(args);
context.publishEvent(new MyApplicationEvent(new Object()));
context.close();
}
}
二、配置监听器的方式原理
1.方式三实现,在application.properties中添加context.listener.classes配置项配置
查看:DelegatingApplicationListener
public class DelegatingApplicationListener
implements ApplicationListener<ApplicationEvent>, Ordered { // NOTE: Similar to org.springframework.web.context.ContextLoader private static final String PROPERTY_NAME = "context.listener.classes";
核心逻辑
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
if (delegates.isEmpty()) {
return;
}
this.multicaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<ApplicationEvent> listener : delegates) {
this.multicaster.addApplicationListener(listener);
}
}
if (this.multicaster != null) {
this.multicaster.multicastEvent(event);
}
} @SuppressWarnings("unchecked")
private List<ApplicationListener<ApplicationEvent>> getListeners(
ConfigurableEnvironment environment) {
if (environment == null) {
return Collections.emptyList();
}
String classNames = environment.getProperty(PROPERTY_NAME);
List<ApplicationListener<ApplicationEvent>> listeners = new ArrayList<ApplicationListener<ApplicationEvent>>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.commaDelimitedListToSet(classNames)) {
try {
Class<?> clazz = ClassUtils.forName(className,
ClassUtils.getDefaultClassLoader());
Assert.isAssignable(ApplicationListener.class, clazz, "class ["
+ className + "] must implement ApplicationListener");
listeners.add((ApplicationListener<ApplicationEvent>) BeanUtils
.instantiateClass(clazz));
}
catch (Exception ex) {
throw new ApplicationContextException(
"Failed to load context listener class [" + className + "]",
ex);
}
}
}
AnnotationAwareOrderComparator.sort(listeners);
return listeners;
}
2、方式四实现
查看:EventListenerMethodProcessor的processBean
protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
annotatedMethods = MethodIntrospector.selectMethods(targetType,
new MethodIntrospector.MetadataLookup<EventListener>() {
@Override
public EventListener inspect(Method method) {
return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
}
});
}
catch (Throwable ex) {
// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
}
}
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetType);
if (logger.isTraceEnabled()) {
logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
}
}
else {
// Non-empty set of methods
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(
method, this.applicationContext.getType(beanName));
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener)
.init(this.applicationContext, this.evaluator);
}
this.applicationContext.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
EventListener
annotatedMethods = MethodIntrospector.selectMethods(targetType,
new MethodIntrospector.MetadataLookup<EventListener>() {
@Override
public EventListener inspect(Method method) {
return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
}
});
查看for
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(
method, this.applicationContext.getType(beanName));
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener)
.init(this.applicationContext, this.evaluator);
}
this.applicationContext.addApplicationListener(applicationListener);
break;
}
}
}
其中factory即EventListenerFactory factory
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.context.event; import java.lang.reflect.Method; import org.springframework.context.ApplicationListener; /**
* Strategy interface for creating {@link ApplicationListener} for methods
* annotated with {@link EventListener}.
*
* @author Stephane Nicoll
* @since 4.2
*/
public interface EventListenerFactory { /**
* Specify if this factory supports the specified {@link Method}.
* @param method an {@link EventListener} annotated method
* @return {@code true} if this factory supports the specified method
*/
boolean supportsMethod(Method method); /**
* Create an {@link ApplicationListener} for the specified method.
* @param beanName the name of the bean
* @param type the target type of the instance
* @param method the {@link EventListener} annotated method
* @return an application listener, suitable to invoke the specified method
*/
ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method); }
三、spring、Spring boot内置事件
1.Spring
jar包:Spring-context-4.3.13.RELEASE
包:org.springframwork.context.event;
常用:ContextClosedEvent、ContextStartedEvent、ContextStopedEvent
示例
@Component
public class MyEventHandle {
@EventListener
public void event2(ContextStoppedEvent event) {
System.out.println("应用停止 接收到事件:" + event.getClass());
}
}
当然:app中Context要停止
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(App.class);
ConfigurableApplicationContext context = app.run(args);
context.publishEvent(new MyApplicationEvent(new Object()));
context.stop();
}
}
2.Spring-boot
jar包:Spring-boot-1.5.9.RELEASE
包:org.springframework.boot.context.event;
常用:ApplicationEnvironmentPreparedEvent、ApplicationFailedEvent等
009-Spring Boot 事件监听、监听器配置与方式、spring、Spring boot内置事件的更多相关文章
- extjs组件添加事件监听的三种方式
extjs对组件添加监听的三种方式 在定义组件的配置时设置 如代码中所示: Java代码 xtype : 'textarea', name : 'dataSetField', labelSe ...
- 王立平--android事件监听的3种方式
第一种通常在activity组件的oncreate事件中直接定义,直接动作. 这样的方式每一个控件都定义一次.通常不方便. Button btn = (Button) findViewById(R.i ...
- [转]extjs组件添加事件监听的三种方式
原文地址:http://blog.csdn.net/y6300023290/article/details/18989635 1.在定义组件配置的时候设置 xtype : 'textarea', na ...
- Spring Boot实践——事件监听
借鉴:https://blog.csdn.net/Harry_ZH_Wang/article/details/79691994 https://blog.csdn.net/ignorewho/arti ...
- SpringBoot的事件监听
事件监听的流程分为三步:1.自定义事件,一般是继承ApplicationEvent抽象类.2.定义事件监听器,一般是实现ApplicationListener接口.3.a.启动的时候,需要将监听器加入 ...
- 关于事件监听机制的总结(Listener和Adapter)
记得以前看过事件监听机制背后也是有一种设计模式的.(设计模式的名字记不清了,只记得背后实现的数据结构是数组.) 附上事件监听机制的分析图: 一个事件源可以承载多个事件(只要这个事件源支持这个事件就可以 ...
- js事件监听
/* 事件监听器 addEventListener() removeEventListener() 传统事件绑定: 1.重复添加会,后添加的后覆盖前面的. */ 示例代码中的html结构: <b ...
- [JS]笔记12之事件机制--事件冒泡和捕获--事件监听--阻止事件传播
-->事件冒泡和捕获-->事件监听-->阻止事件传播 一.事件冒泡和捕获 1.概念:当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,点击子元素时,父元素的oncl ...
- JS的事件监听机制
很久以前有个叫Netscape的姑娘,她制订了Javascript的一套事件驱动机制(即事件捕获) 后来又有一个叫“IE”的小子,这孩子比较傲气,他认为“凭什么我要依照你的规则走”,于是他又创造了一套 ...
随机推荐
- c# WPF SVG 文件的引用(SharpVectors)
原文:c# WPF SVG 文件的引用(SharpVectors) 阿里巴巴矢量图标库提供了大量的 SVG 图标:https://www.iconfont.cn/ 但是 WPF 本身不支持 SVG 格 ...
- OneinStack定时同步备份数据库/网站至七牛云存储方法
无论我们用WEB面板,还是用一键脚本安装环境建站,只要一旦我们开始用VPS.服务器,最为关键的就是服务器中的数据.因为大部分VPS.服务器商家都是无管理型主机,任何的安装和维护都需要我们自行管理.即便 ...
- 关于prepareStatement(String sql,int autoGeneratedKeys)的记录
PreparedStatement prepareStatement(String sql,int autoGeneratedKeys) throws SQLException autoGenerat ...
- 几个有关FPGA的概念
<数字设计——原理和实践>(John F.Wakerly)的书 FPGA同步时钟设计 简单说就是 一个系统中(或系统中的一部分)都采用同一个时钟触发.系统中的(D)触发器全部都连接到一个时 ...
- PAT Basic 1015 德才论 (25 分)
宋代史学家司马光在<资治通鉴>中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人 ...
- ascii 八进制
int main() 4 { 5 char buf[20] = {'\101','\102','\103',0}; 6 printf("%s",buf); 7 return 0; ...
- Thymeleaf 整理
1.标准变量表达式: thymeleaf中的变量表达式使用${变量名}的方式获取其中的数据 th:text="" 是thymeleaf的一个属性,用于文本的显示 如:<spa ...
- Flutter SDK安装(windows)
Flutter集成了Dart,因此不需要单独安装dart-sdk.Flutter的SDK可以从官网下载:https://flutter.io/sdk-archive/#windows 在Flutter ...
- java8 时间日期操作包总结
- python 7行代码实现微信机器人自动回复
首先 需要去 图灵 网站注册 获取api_key 先上代码 from wxpy import * bot = Bot() tuling = Tuling(api_key='你的api_key') @b ...