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. Python 2.7 学习笔记 列表的使用

    同其它编程语言一样,python也提供了丰富的数据结构,以方便数据的处理.本文介绍两种最基本的数据集合,列表和元组的使用. 一.列表使用介绍 可以理解为一个有序的序列.其使用方式举例如下: list= ...

  2. 基于springmvc的简单增删改查实现---中间使用到了bean validation

    package com.kite.controller; import java.util.HashMap; import java.util.Map; import javax.validation ...

  3. redis(二)redis+TCMALLOC高性能的缓存服务器的安装配置

    安装  1准备编译环境    yum -y install gcc gcc+ gcc-c++ openssl openssl-devel pcre pcre-devel  2 下载源码包(由于goog ...

  4. vs2016 创建 vsto excel 文件项目的一个问题

    新工作需要些一个基于Excel开发一个工具,vs的 vsto 功能很好用,封装了基于开发office 开的一些工具.但是在实际使用时,创建项目总是报错,提示打开excel文件失败.项目是需要创建一个e ...

  5. 基于Qt的FreeType字体轮廓解析

    一.本文目的 以前的文档中.详细的介绍了FreeType开源字体引擎库的基础知识.基本用法.但并未详细的阐明在TurboCG中.是如何解析出一个文字的轮廓的,本文集中阐述.怎么样使用FreeType开 ...

  6. or1200构建sopc系统之软件环境搭建

    使用预先编译好的工具链 下载: ftp://ocuser:oc@195.67.9.12/toolchain/or32-elf-linux-x86.tar.bz2 解压 tar xjf or32-elf ...

  7. ORACLE FLASHBACK DATABASE 知识整理

    1.知识储备 1)    只有SYSDBA有权执行,闪回前一定要记录当前SCN 2)    需要停机,并要求处于ARCHIVELOG模式中 3)    闪回日志不能被复用和归档,是自动管理的.RVWR ...

  8. 浅谈初次搭建nginx+php+mysql遇到的问题

    先说明下我linux上的环境: nginx + php(5.5.10) + mysql 開始的源代码已经在本地写好,并调试成功(本地的环境是用XAMPP的默认配置).在把代码上传至linux上时,出现 ...

  9. Cloud Foundry 中国群英会【上海站、成都站】资料宣传

    关注云计算和PaaS层的童鞋可以了解下: http://www.cloudfoundry-heroes-summit.com/shanghai http://www.cloudfoundry-hero ...

  10. 将 mp3 等音乐资源以资源形式嵌入 exe 文件中

    引用:http://www.easyx.cn/skills/View.aspx?id=6 本文讲解怎样将 mp3 等音乐资源以资源形式嵌入 exe 文件中,并通过 mciSendString 调用.嵌 ...