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

  • 11
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
XML越来越热,关于XML的基础教程网络上也随处可见。可是一大堆的概念和术语往往让人望而生畏,很多朋友问我:XML到底有什么用,我们是否需要学习它?我想就我个人学习过程的心得和经验,写一篇比较全面的介绍文章。首先有两点是需要肯定的:   第一:XML肯定是未来的发展趋势,不论是网页设计师还是网络程序员,都应该及时学习和了解,等待只会让你失去机会;   第二:新知识肯定会有很多新概念,尝试理解和接受,您才可能提高。不要害怕和逃避,毕竟我们还年轻。   本文共分五大部分。分别是XML快速入门,XML的概念,XML的术语,XML的实现,XML的实例分析。最后附录介绍了XML的相关资源。作者站在普通网页设计人员的角度,用平实生动的语言,向您讲述XML的方方面面,帮助你拨开XML的神秘面纱,快速步入XML的新领域。 • 第一章:XML快速入门 • 一. 什么是XML? • 二. XML是新概念吗? • 三. 使用XML有什么好处? • 四. XML很难学吗? • 五. XML和HTML的区别 • 六. XML的严格格式 • 七. 关于XML的更多 • 第二章:XML概念 • 一. 扩展性 • 二. 标识 • 三. 语言 • 四. 结构化 • 五. Meta数据 • 六. 显示 • 七. DOM • 第三章:XML的术语 • 导言 • 一.XML文档的有关术语 • 二.DTD的有关术语 • 第四章:XML的语法 • 一.XML语法规则 • 二.元素的语法 • 三.注释的语法 • 四.CDATA的语法 • 五.Namespaces的语法 • 六.entity的语法 • 七.DTD的语法 • 第五章:XML实例解释 • 一.定义新标识 • 二.建立XML文档 • 三.建立相应的HTML文件 • 第六章:XML相关资源 五. XML和HTML的区别 XML和HTML都来自于SGML,它们都含有标记,有着相似的语法,HTML和XML的最大区别在于:HTML是一个定型的标记语言,它用固有的标记来描述,显示网页内容。比如表示首行标题,有固定的尺寸。相对的,XML则没有固定的标记,XML不能描述网页具体的外观,内容,它只是描述内容的数据形式和结构。 这是一个质的区别:网页将数据和显示混在一起,而XML则将数据和显示分开来。 我们看上面的例子,在myfile.htm,我们只关心页面的显示方式,我们可以设计不同的界面,用不同的方式来排版页面,但数据是储存在myfile.xml,不需要任何改变。 (如果你是程序员,你会惊讶的发现,这与模块化面向对象编程的思想极其相似!其实网页何尝不是一种程序呢?) 正是这种区别使得XML在网络应用和信息共享上方便,高效,可扩展。所以我们相信,XML做为一种先进的数据处理方法,将使网络跨越到一个新的境界。 六. XML的严格格式 吸取HTML松散格式带来的经验教训,XML一开始就坚持实行"良好的格式"。 我们先看HTML的一些语句,这些语句在HTML随处可见: 1. sample 2.sample 3.sample 4.samplar 在XML文档,上述几种语句的语法都是错误的。因为: 1.所有的标记都必须要有一个相应的结束标记; 2.所有的XML标记都必须合理嵌套; 3.所有XML标记都区分大小写; 4.所有标记的属性必须用""括起来; 所以上列语句在XML正确的写法是 1. sample 2.sample 3.sample 4.samplar   另外,XML标记必须遵循下面的命名规则: 1.名字可以包含字母、数字以及其它字母; 2.名字不能以数字或"_" (下划线) 开头; 3.名字不能以字母 xml (或 XML 或 Xml ..) 开头; 4.名字不能包含空格。 在XML文档任何的差错,都会得到同一个结果:网页不能被显示。各浏览器开发商已经达成协议,对XML实行严格而挑剔的解析,任何细小的错误都会被报告。你可以将上面的myfile.xml修改一下,比如将改为,然后用IE5直接打开myfile.xml,会得到一个出错信息页面: XML轻松学习手册 ajie <E

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值