Spring对事件有一些支持,因为项目须要,所以近期小小研究了下究竟这个怎么能够方便的用在实际项目其中来。

说起事件这个东西,事实上就是借鉴的那个观察者模式。这里面涉及到事件源、事件监听者、事件公布者三个概念。

事件就是当我们改动一些数据之后,可能须要把这些改动后的数据告诉其它模块或者业务,使用事件后。当我改动了数据后。会公布一个事件。

那些关心我数据变化的,仅仅须要继承BasicService而且事件源和我的一样,他就会收到这个事件的通知。

这个,有个弊端就是多个事件源的时候,怎么通知。

以后再优化吧。

先处理起简单的业务再说。慢慢来吧。

直接来样例比較好说一些。须要使用到Spring的jar包。

首先看底层封装的事件源。

package com.mine.event.basic.event;

import java.util.List;

import org.springframework.context.ApplicationEvent;

import com.mine.event.basic.enums.EventTypeEnum;

/**
*
* @author 2014-11-3 下午07:06:20
* @version V1.0
*/
public class BasicEvent extends ApplicationEvent { /** * 序列化ID */
private static final long serialVersionUID = 7519966952568731040L; public BasicEvent(Object object){
super(object);
} private EventTypeEnum eventTypeEnum; /**
* 事件通知的内容列表
*/
private List<? > eventList; /***
* 事件通知内容单个
*/
private Object eventObject; public void setEventList(List<? > eventList) {
this.eventList = eventList;
} public List<?> getEventList() {
return eventList;
} public void setEventTypeEnum(EventTypeEnum eventTypeEnum) {
this.eventTypeEnum = eventTypeEnum;
} public EventTypeEnum getEventTypeEnum() {
return eventTypeEnum;
} public void setEventObject(Object eventObject) {
this.eventObject = eventObject;
} public Object getEventObject() {
return eventObject;
}
}

然后就是事件监听者、事件公布者。

这里设计到一个类中的缘故是方便实现者。不须要实现者写那么多内容。

package com.mine.event.basic.service;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener; import com.mine.event.basic.enums.EventTypeEnum;
import com.mine.event.basic.event.BasicEvent;
/**
*
* @author 2014-11-3 下午07:11:53
* @version V1.0
*/
public abstract class BasicService<T extends BasicEvent> implements ApplicationContextAware,ApplicationListener<BasicEvent>{ public abstract Class fetchCurrentEvent(); private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
} /**
* 添加单个对象并公布事件
* @author 2014-11-5 上午09:15:25
* @param object
*/
public void addSingleObj(Object object){ Object event = getEventObject(object,EventTypeEnum.ADD); applicationContext.publishEvent((ApplicationEvent)event);
}
/** 通过反射实例化对象和设置事件类型
* @author 2014-11-5 上午11:53:39
* @param object
* @param eventTypeEnum 事件类型
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked","finally" })
private Object getEventObject(Object object,EventTypeEnum eventTypeEnum){
//获取构造方法
Object event = null;
try {
Class eventClass = fetchCurrentEvent();
Constructor constructor = fetchCurrentEvent().getConstructor(Object.class);
event = constructor.newInstance(this);
//获取setEventObject方法
Method method = eventClass.getMethod("setEventObject",Object.class);
//调用setEventObject方法
method.invoke(event,object);
//获取设置事件枚举的方法
Method enuMethod = eventClass.getMethod("setEventTypeEnum", EventTypeEnum.class);
enuMethod.invoke(event,eventTypeEnum);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}finally{
return event;
}
} /***
* 须要实现者完毕的详细事件内容
* @author 2014-11-5 上午09:14:58
* @param event
*/
public abstract void notifyEvent(BasicEvent event); /**
*事件
*/
@Override
public void onApplicationEvent(BasicEvent event) {
String eventString = event.getClass().toString();
String currentString = fetchCurrentEvent().toString();
//同样类型的事件才会进行通知
if (eventString.equals(currentString)) {
notifyEvent(event);
}
}
}

然后就是事件类型,採用枚举的方式,简单的分为添加、改动、删除。

package com.mine.event.basic.enums;
/**
* 事件类型
* @author 2014-11-3 下午07:02:09
* @version V1.0
*/
public enum EventTypeEnum { ADD,//添加
DEL,//删除
MODIFY//改动
}

以下进行样例的演示

首先定义一个实体User
package com.mine.event.entity;

/**
*
* @author 2014-11-3 下午06:59:26
* @version V1.0
*/
public class User { private Integer id; private String name; public int getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public User(Integer id, String name) {
super();
this.id = id;
this.name = name;
} public void setName(String name) {
this.name = name;
} }

然后是事件源

package com.mine.event.event;

import com.mine.event.basic.event.BasicEvent;

/**
* 用户相关事件
* @author 2014-11-3 下午07:06:09
* @version V1.0
*/
public class UserEvent extends BasicEvent{ /** * 序列化ID */
private static final long serialVersionUID = 7117267688533263478L; public UserEvent(Object object) {
super(object);
} }
这个主要是对照用的。
package com.mine.event.event;

import com.mine.event.basic.event.BasicEvent;

public class TEvent extends BasicEvent {

	public TEvent(Object object) {
super(object);
} }

然后是定义一个Service。并且它既是监听者又是公布者。

package com.mine.event.service;

import com.mine.event.basic.enums.EventTypeEnum;
import com.mine.event.basic.event.BasicEvent;
import com.mine.event.basic.service.BasicService;
import com.mine.event.entity.User;
import com.mine.event.event.UserEvent; public class UserService extends BasicService<UserEvent> { /**
* 添加用户
*
* @author 2014-11-3 下午07:18:16
* @param user
*/
public void addUser(User user) {
this.addSingleObj(user);
} /**
* 依据事件类型进行对应的处理
*/
@Override
public void notifyEvent(BasicEvent event) { //假设UserEvent有自己定义的属性或方法。以下须要调用的,则须要强制转换为UserEvent
// UserEvent userEvent = (UserEvent) event; EventTypeEnum typeEnum = event.getEventTypeEnum(); User user = (User)event.getEventObject();
if (user == null) {
return;
}
switch (typeEnum) {
case ADD:
System.out.println("ADD:" + user.getName());
break;
case MODIFY:
System.out.println("MODIFY:" + event.getEventObject());
break;
case DEL:
System.out.println("DEL:" + event.getEventObject());
break;
default:
System.out.println("其他");
break;
}
} @Override
public Class fetchCurrentEvent() {
return UserEvent.class;
}
}

以下的和这个主要是用来对照的,由于这个事件源是TEvent。所以UserEvent事件发生后,UserServiceTemp不会收到通知。

由于BasicService在进行事件通知时会比对事件源是否一样。一样的才会进行通知。
package com.mine.event.service;

import com.mine.event.basic.enums.EventTypeEnum;
import com.mine.event.basic.event.BasicEvent;
import com.mine.event.basic.service.BasicService;
import com.mine.event.entity.User;
import com.mine.event.event.TEvent; public class UserServiceTemp extends BasicService<TEvent>{ /**
* 添加用户
*
* @author 2014-11-3 下午07:18:16
* @param user
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {改动人} 2014-11-3
* @modify by reason:{原因}
*/
public void addUser(User user) {
this.addSingleObj(user);
} /**
* 依据事件类型进行对应的处理
*/
public void notifyEvent(BasicEvent event) { //假设UserEvent有自己定义的属性或方法。以下须要调用的,则须要强制转换为UserEvent
// UserEvent userEvent = (UserEvent) event; EventTypeEnum typeEnum = event.getEventTypeEnum(); User user = (User)event.getEventObject();
if (user == null) {
return;
}
switch (typeEnum) {
case ADD:
System.out.println("UserServiceTempADD:" + user.getName());
break;
case MODIFY:
System.out.println("MODIFY:" + event.getEventObject());
break;
case DEL:
System.out.println("DEL:" + event.getEventObject());
break;
default:
System.out.println("其他");
break;
}
} public Class fetchCurrentEvent() {
return TEvent.class;
}
}

以下是Sping的一些配置

<?xml version="1.0" encoding="UTF-8"?

>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="userServiceImpl" class="com.mine.event.service.UserService" />
<bean id="userServiceTemp" class="com.mine.event.service.UserServiceTemp" />
</beans>

最后是一个測试类

package com.mine.event.test;

import java.util.Collection;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mine.event.basic.service.BasicService;
import com.mine.event.entity.User;
import com.mine.event.service.UserService; public class TestUserEvent { public static void main(String[] args) { User user = new User(1,"name_1"); ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = applicationContext.getBean("userServiceImpl",UserService.class); userService.addUser(user); Collection<BasicService> collection = applicationContext.getBeansOfType(BasicService.class).values(); //通过Spring能够获得全部载入到Spring上下文中的一个类的子类。
System.out.println("获取BasicService的全部载入到Spring上下文其中的全部子类个数"+collection.size());
}
}

Spring的事件处理的更多相关文章

  1. Spring入门学习笔记(3)——事件处理类

    目录 Spring中的事件处理 Spring内建事件 监听Context事件 Example 自定义Spring事件 Spring中的事件处理 ApplicationContext 是Spring的核 ...

  2. Spring(九)之事件处理

    Spring的核心是ApplicationContext,它管理bean的完整生命周期.ApplicationContext在加载bean时发布某些类型的事件.例如,ContextStartedEve ...

  3. Spring中的事件处理

    文章目录 Spring中的事件处理 Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期.当加载 beans 时,ApplicationContext ...

  4. Spring 中的事件处理

    Spring 中的事件处理 Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期.当加载 beans 时,ApplicationContext 发布某些 ...

  5. 01.Spring Ioc 容器

    基本概念 Spring 的 Ioc 容器,通常也称应用上下文.它包含了两个概念 Ioc 和 容器: 容器:顾名思义就是用来装东西的,在 Spring 中容器里盛放的就是各种各样的 Bean.既然装了东 ...

  6. Spring IoC和AOP的介绍

    基于Spring Framework 版本:5.0.2.RELEASE IoC 概念:传统Java开发中,程序通过new主动创建对象实例,而Spring有专门的IoC容器来创建对象,具体来说就是在Sp ...

  7. Spring教程检视阅读

    Spring教程检视阅读 地址 可供参考的教程 <菜鸟学 SSH> <Spring Boot 那些事> <初识 Spring Security> <Sprin ...

  8. Sping框架初步使用1

    Spring核心容器的理论:Spring核心容器就是一个超大工厂,所有的对象都会被当成Spring容器的核心管理对象,Spring把容器中一切对象统称为Bean(只要是一个Java类,Spring就可 ...

  9. Eureka Server启动过程

    前面对Eureka的服务端及客户端的使用均已成功实践,对比Zookeeper注册中心的使用区别还是蛮大的: P:分区容错性(⼀定的要满⾜的)C:数据⼀致性 A:⾼可⽤:CAP不可能同时满⾜三个,要么是 ...

随机推荐

  1. Raphael入门实例:绘图

    raphael 实例 开始 创建画布参数说明 创建一个画布对象. 下面每个例子都会创建一个320*200大小的画布. ? 1 2 // 1.在视口的 (10,50) 坐标位置上创建画布 var pap ...

  2. configure.ac

    # # Copyright (C) - Tobias Brunner # Copyright (C) - Andreas Steffen # Copyright (C) - Martin Willi ...

  3. 《Java并发编程实战》第十四章 构建自己定义的同步工具 读书笔记

    一.状态依赖性的管理 有界缓存实现的基类 @ ThreadSafe public abstract class BaseBoundedBuffer<E> { @GuardeBy( &quo ...

  4. Java进阶04 RTTI

    链接地址:http://www.cnblogs.com/vamei/archive/2013/04/14/3013985.html 作者:Vamei 出处:http://www.cnblogs.com ...

  5. 如何在VMware中修改Mac OS的屏幕分辨率

    关于mac os分辨率问题:方法一:临时方法,只对当次启动有效,即在启动倒计时的时候,回车,等待输入参数是输入如下文本:“Graphics Mode"="1280x800x32@6 ...

  6. 相邻数字的基数不等比:skew数

    2973:Skew数 描述在 skew binary表示中, 第 k 位的值xk表示xk*(2k+1-1). 每个位上的可能数字是0 或 1,最后面一个非零位可以是2, 例如, 10120(skew) ...

  7. Oracle数据库索引使用及索引失效总结

    容易引起oracle索引失效的原因很多: 1.在索引列上使用函数.如SUBSTR,DECODE,INSTR等,对索引列进行运算.需要建立函数索引就可以解决了. 2.新建的表还没来得及生成统计信息,分析 ...

  8. [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传

    原文 [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传 Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件 ...

  9. Spring注入静态变量(转)

    今天碰到一个问题,我的一个工具类提供了几种静态方法,静态方法需要另外一个类的实例提供处理,因此就写出了这样的代码: Class Util{ private static XXX xxx; xxx = ...

  10. http://www.cutt.com/

    简网APP工场-服务介绍 服务介绍