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”的小子,这孩子比较傲气,他认为“凭什么我要依照你的规则走”,于是他又创造了一套 ...
随机推荐
- python学习五十五天subprocess模块的使用
我们经常需要通过python去执行一条系统执行命令或者脚本,系统的shell命令独立于你python进程之外的,没执行一条命令,就发起一个新的进程, 三种执行命令的方法 subprocess.run( ...
- 剑指offer-二叉树的镜像-python
题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...
- Spring的底层实现机制
Spring的底层实现机制是通过Demo4j+java反射机制实现的. 使用demo4j来解析xml,使用反射机制实例化bean.
- 【问题解决方案】git仓库重构
Linux mv命令 用来为文件或目录改名.或将文件或目录移入其它位置. 语法 mv [options] source dest mv [options] source... directory 注: ...
- 自定义ajax函数(仿照jQuery)
AJAX介绍 AJAX = 异步 JavaScript 和 XML. 全称:Asynchronous Javascript And XML: AJAX 是一种用于创建快速动态网页的技术. 通过在后台与 ...
- HTML A标签 href click事件冲突
转自:https://blog.csdn.net/xinglu/article/details/45199337
- lldb调试命令
XCode4.0以后,编译器换成了LLVM 编译器 2.0 与以前相比,更加强大:1.LLVM 编译器是下一带开源的编译技术.完全支持C, Objective-C, 和 C++.2.LLVM 速度比 ...
- 2018-8-10-dotnet-core-编程规范
title author date CreateTime categories dotnet core 编程规范 lindexi 2018-08-10 19:16:52 +0800 2018-05-0 ...
- ElasticSearch - 解决ES的深分页问题 (游标 scroll)
https://www.jianshu.com/p/f4d322415d29 1.简介 ES为了避免深分页,不允许使用分页(from&size)查询10000条以后的数据,因此如果要查询第10 ...
- Linux日常之Ubuntu系统中sendmail的安装、配置、发送邮件
一. 安装 1. sendmail必须先要安装两个包 (1)sudo apt-get install sendmail (2)sudo apt-get install sendmail-cf 2. u ...