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. Windows多线程

    //简单的引出多线程是肿么回事儿....当点击下载的时候,下载内容还没结束也可以点击资源库,其实这就用了另一个线程,弹出“下载完成”对话框的时候,没有点击确定是不能点击主页面内容的,这就是用----- ...

  2. [转]PostgreSQL事务处理机制

    原文链接:http://blog.chinaunix.net/uid-20726500-id-4040024.html 事务的实现原理可以解读为DBMS采取何种技术确保事务的ACID特性.Postgr ...

  3. django局域网建一个网站

    之前总是运行的python manage.py runserver,用默认的在本机访问的127.0.0.1:8000,如果跟几个同学一起去开发一个网站来玩玩的话,可以这样: python manage ...

  4. Git 将本次修改追加在上一次修改上面

    Git 将本次修改追加在上一次修改上面 git add . git commit --amend 之后就是进入日志提交页面 确保change-Id那条记录出现在最后一行,如: zh-->en 修 ...

  5. MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件

    原文  MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件 UI 前沿技术 WPF 中的多点触控操作事件 Charles Petzold 下载代码示例 就在过去几年,多点触控还只是科幻电 ...

  6. oracle exp实例

    exp nam/pwd@ip:1521:databasename  log=/tmp/export.log  file=/tmp/oracle_database.dmp ./exp cmsuser/x ...

  7. EF 简单的 CRUD、分页 代码笔记

    添加: static void Main(string[] args)        {            CCDBEntities ccdbContext = new CCDBEntities( ...

  8. STM32启动模式

    STM32三种启动模式对应的存储介质均是芯片内置的,它们是: 1)用户闪存 = 芯片内置的Flash.2)SRAM = 芯片内置的RAM区,就是内存啦.3)系统存储器 = 芯片内部一块特定的区域,芯片 ...

  9. truncate 和 delete 差异

    truncate table players; 相当于 delete from players;要么 delete players from players;  要么 delete players.* ...

  10. uva 10127 - Ones(数论)

    题目链接:uva 10127 - Ones 题目大意:给出n,问说者少要多少为1才干够整除n. 解题思路:等于是高精度取模,直到余数为0为止. #include <cstdio> #inc ...