spring中自定义Event事件的使用和浅析
在我目前接触的项目中,用到了许多spring相关的技术,框架层面的spring、spring mvc就不说了,细节上的功能也用了不少,如schedule定时任务、Filter过滤器、 interceptor拦截器等等,而这一篇我要说的是spring Event自定义事件,目前的项目中似乎没怎么用,但是这一项技术貌似还蛮重要,所以也不能不掌握。
对于事件驱动模型的解释和理解,我觉得有一篇博客里说的非常好,尤其是在解释这个关系的时候,举的交通信号灯的例子非常贴切,这里就引用做一个简单的解释:
事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点:
1. 首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方);
2. 当目标发送改变(发布),观察者(订阅者)就可以接收到改变;
3. 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的),目标无需干涉;所以就松散耦合了它们之间的关系。
引用的原文地址:http://xls9577087.iteye.com/blog/2121752(这篇文章中还讲解了有序监听和无序监听、异步事件等等,有兴趣的也可以去那里了解学习一下)
当我们对事件驱动有一个简单的理解之后,就能大概知道它应该什么时候用,然后再来研究它该怎么用,单一的文字或许不太容易解释,还是先把代码弄上来,然后再结合起来解释。
首先自定义一个事件,需要继承ApplicationEvent类,相当于安装了一个没有通电,没有灯光的信号灯,需要具有信号灯的基本特征。
package springTest5;
import org.springframework.context.ApplicationEvent;
public class EventTest extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private String message;
public EventTest(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
然后再创建一个监听类,相当于行人(不管是否使用交通工具),需要实现ApplicationListener接口,并且重写onApplicationEvent方法,可以理解成这个行人需要看信号灯,并且能理解信号灯的意思才行。否则不看信号灯跟没有信号灯没有区别,看了不理解也没用。
package springTest5;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class ListenerTest1 implements ApplicationListener<EventTest> {
public void onApplicationEvent(EventTest event) {
System.out.println("test1:" + event.getMessage());
}
}
这里的注解就只是简单的声明一个bean,应该不需要太多的解释。
那么第三步自然是需要一个控制信号灯变化的东西,相当于是给他接好电线,给他一个正常变换红黄绿的程序和电路。
package springTest5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class EventPbulish {
@Autowired
ApplicationContext context;
public void publish(String message) {
context.publishEvent(new EventTest(this, message));
}
}
到这里,实际上已经写完了,但是呢很明显,我们合理没有配置文件,那么这里的注解也是不能被spring使用的,纯粹是个摆设,所以还需要一个配置文件,或者说相当于配置文件的配置类,要让相关的类生效。
package springTest5;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("springTest5")
public class ConfigTest {
}
对于这里两个注解的意思,前几天的文章曾多次解释,因此这里便不说了,真有不懂得,可以翻一下前几天的博客。
走到这里,相当于我们创建好了一个可以正常运行的信号灯,创建好了一个正常的行人,但是呢都是静止不动的,我们需要让他动起来,也就是main方法的测试,相当于让行人开始看灯,让电路开始通电。
package springTest5;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigTest.class);
EventPbulish eventPbulish = context.getBean(EventPbulish.class);
eventPbulish.publish("zhangsan");
context.close();
}
}
运行main方法后结果如下:
根据上边的代码可以知道代表这个事件正常运行了,也就是信号灯正常发出了光,行人正常接收到了消息。
那么还有一个细节在于,信号灯对行人,是一对多的关系,那么这里的事件是否确实如此呢?为了验证,我便再写一个监听,再new一个行人,其他一切不变。
package springTest5;
import org.springframework.context.ApplicationListener;
@Component
public class ListenerTest2 implements ApplicationListener<EventTest> {
public void onApplicationEvent(EventTest event) {
System.out.println("tst2:" + event.getMessage());
}
}
再次运行main方法,结果如下:‘
很明显,两个行人都正常接收到了信号灯的信号。
那么,根据上边一开始的解释,再加上之后的例子,我们应该大概知道了这里的一个完整的事件包含些什么内容:即要有目标,也就是一个事件;还要有接受目标信息的对象,也就是一种监听;还要有改变或者说发出信息的一个控制体。
到这里基本上就算是完工了,这算是最简单的实现方式,像一些细节上的,把配置类改配置文件等等,都可以自己适当的变型。
在结尾处,结合@PropertySource注解,我把上边的列子做了个小小的变型,模拟一个找人的广播,喊一个人的名字,然后听到的人进行相应的回答。
这个例子和上边的不同在于,增加了一个properties配置,用来给接收对象初始化名称,顺便练习@PropertySource注解。
name1=zhangsan
name2=lisi
然后修改了一下监听类,从properties文件中获取自己的名字。
package springTest5;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.stereotype.Component;
@Component
@PropertySource("test.properties")
public class ListenerTest1 implements ApplicationListener<EventTest> {
@Value("${name1}")
String name;
public void onApplicationEvent(EventTest event) {
if (event.getMessage().equals(name)) {
System.out.println("you need to find " + event.getMessage() + ",yes, I'am " + name);
} else {
System.out
.println("you need to find " + event.getMessage() + ",but I'am not " + event.getMessage() + ",I'am " + name);
}
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigure() {
return new PropertySourcesPlaceholderConfigurer();
}
}
其中propertyConfigure()是必须的,只有写了这个才能正产刚从properties中获取数据,但是经过测试,这一段代码只需要有一个地方出现了就可以,因此第二个监听类就不用再写:
package springTest5;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("test.properties")
public class ListenerTest2 implements ApplicationListener<EventTest> {
@Value("${name2}")
String name;
public void onApplicationEvent(EventTest event) {
if (event.getMessage().equals(name)) {
System.out.println("you need to find " + event.getMessage() + ",yes, I'am" + name);
} else {
System.out
.println("you need to find " + event.getMessage() + ",but I'am not " + event.getMessage() + ",I'am " + name);
}
}
}
在运行之前的main方法后,结果如下:
这个例子已经打包上传,有兴趣的可以看看,其中只有springTest5这个包里是这个例子,其他几个包里的内容则是对前几天的博文中对profile等技术点的练习,有兴趣的也可以看看。
http://download.csdn.net/detail/tuzongxun/9711034
spring中自定义Event事件的使用和浅析的更多相关文章
- Spring中ApplicationContext对事件的支持
Spring中ApplicationContext对事件的支持 ApplicationContext具有发布事件的能力.这是因为该接口继承了ApplicationEventPublisher接口. ...
- 6.2 dubbo在spring中自定义xml标签源码解析
在6.1 如何在spring中自定义xml标签中我们看到了在spring中自定义xml标签的方式.dubbo也是这样来实现的. 一 META_INF/dubbo.xsd 比较长,只列出<dubb ...
- 6.1 如何在spring中自定义xml标签
dubbo自定义了很多xml标签,例如<dubbo:application>,那么这些自定义标签是怎么与spring结合起来的呢?我们先看一个简单的例子. 一 编写模型类 package ...
- Spring学习六:自定义Event事件
Spring 中的自定义事件 编写和发布自己的自定义事件有许多步骤.按照在这一章给出的说明来编写,发布和处理自定义 Spring 事件. 步骤 描述 1 创建一个名称为 SpringExample 的 ...
- day05 Spring中自定义注解的用处-之获取自定义的Servie
PS: 在RPC远程调用中,想要获取自定义的service的方法,就得自定义标签遍历拿到方法 PS:在spring中,两个最核心的 概念是aop和ioc,aop其实就是动态代理. ioc 就是解决对象 ...
- 在Spring中使用异步事件实现同步事务
结合Scala+Spring,我们将采取一个很简单的场景:下订单,然后发送一封电子邮件. 编制一个服务: @Serviceclass OrderService @Autowired() (orderD ...
- spring中的异步事件
这里讲解一下Spring对异步事件机制的支持,实现方式有两种: 1.全局异步 即只要是触发事件都是以异步执行,具体配置(spring-config-register.xml)如下: Java代码 ...
- Spring中的ApplicationContext事件机制
ApplicationContext的事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListerner接口来实现. 1. 创建EmailEvent pu ...
- javascript中window.event事件用法详解
转自http://www.jb51.net/article/32564.htm描述 event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等. event对象只在事件发生 ...
随机推荐
- 为什么.Net平台不支持程序集卸载(Assembly.Unload)?
我们知道在.net平台中反射提供了在运行时动态的获得程序或程序集中每一个类型(包括类.结构.委托.接口和枚举等)的成员和成员的信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象.我们知道 ...
- JavaScript 数值Number类型详解
Number 问题 如果下面的问题你都能回答对了吗? 0.1 + 0.2 == 0.3 成立吗? .e-5 表示多少? 怎么表示8进制? 怎么转换进制? 如何将字符串转换成数值或整数?反过来呢?十六进 ...
- template.compile()方法
template.compile(source, options) source:必传,渲染模板的内容. options:可选,通常不传.(其实是我还没研究明白) return:一个渲染函数. 示例如 ...
- mkdir与mkdirs的区别
mkdir与mkdirs的区别 项目中需要在代码中读取或创建文件保存路径,用到了mkdir,查看还有个mkdirs方法,这里记录一下两者的区别. 1.关于两者的说明如下: boolean mkdir( ...
- 用ASOS建立自定义的OpenID 服务(一)-----------简介
翻译文章 原文地址 这一系列共包括9个部分,这是第一部分,下面是英文原文地址: Introduction Choosing the right flow(s) Registering the midd ...
- React 16.3来了:带着全新的Context API
文章概览 React在版本16.3-alpha里引入了新的Context API,社区一片期待之声.我们先通过简单的例子,看下新的Context API长啥样,然后再简单探讨下新的API的意义. 文中 ...
- ServiceStack.OrmLite T4模板使用记录
前言 最近研究了下ServiceStack.OrmLite,文档中也提到了使用T4模板对数据库中已经有了表进行实体的映射,这里也顺便记录下使用的步骤和情况. 开始使用 引用T4模板 首先我们创建一个工 ...
- mysql 删匿名帐户
mysql默认安装,带有匿名帐户 删除它很简单 登录进入msyql并执行以下三行语句: use mysql; delete from user where user=''; flush privile ...
- http目录显示时间与服务器相差8小时
一直用nginx做http服务,代码里访问过文件地址,并未认真关注过访问http目录下的时间戳.今天浏览文件的时候发现一个问题.web上显示的文件时间戳与服务器时间相比差8个小时.具体表现看下图: w ...
- asp.net 文件上传 Uploadify HTML5 带进度条
参考的https://www.cnblogs.com/lvdabao/p/3452858.html这位,在此基础上略有修改: 1.根据Layer,将上传附件做成弹窗显示,引入frame弹窗,在项目当中 ...