1 简介:
只要是事件就是观察者模式,Spring中的Event也不例外,主要应用就是程序解耦,实现本质是广播的形式........屁话不多说
2 Spring的event实现方式:
继承ApplicationEvent即可,但是Spring版本4.2之后不再强制要求继承ApplicationEvent,非Application的子类将被封装成PayloadApplicationEvent:
实现:
import org.springframework.context.ApplicationEvent;
public class MyEvent extends ApplicationEvent {
//todo -----
private String msg;
public MyEvent(Object source) {
super(source);
}
public MyEvent(Object source,String msg) {
super(source);
this.msg=msg;
}
public String getMsg() {
return msg;
}
}
3 事件的推送:
编写事件推送的service实现ApplicationContextAwar接口,或者实现ApplicationEventPublisherAware接口,在需要时候根据业务场景推送事件:
实现:
@Service
public class EventProduceService implements ApplicationContextAware, ApplicationEventPublisherAware {
//实现方式一
private ApplicationContext applicationContext;
//实现方式二
private ApplicationEventPublisher applicationEventPublisher;
/**
* 容器初始化时候会自动的填装该对象
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 容器初始化时候会自动的填装该对象
* @param applicationEventPublisher
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher=applicationEventPublisher;
}
/**
* 实际业务中进行封装数据推送
*/
public void sentEvent(){
//方式一:applicationContext的推送Api可以以根据需要进行选择
applicationContext.publishEvent(new MyEvent(this,"我是一颗小码农"));
//方式二: applicationEventPublisher的推送Api可以以根据需要进行选择
applicationEventPublisher.publishEvent(new MyEvent(this,"今天是20220804"));
}
}
4事件监听器(处理器):
编写事件的处理器,交给Spring的ioc管理即可,实现有两种方式,
(1)通过@EventListener注解标注对应的事件处理器,处理器会根据参数类型自动识别事件类型的
实现:
@Configuration
public class EventConfig {
@EventListener
public void doWithEvent(MyEvent myEvent) {
System.out.println("事件消息是: "+myEvent.getMsg());
}
@EventListener
public void doWithEvent(BEvent myEvent) {
System.out.println("事件消息是: "+myEvent.getMsg());
}
@EventListener
public void doWithEvent(CEvent myEvent) {
System.out.println("事件消息是: "+myEvent.getMsg());
}
}
(2) 实现ApplicationListener<T>接口,处理器会根据泛型类型处理事件
实现
@Component
public class EventHandler implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
//todo----
System.out.println(event.getMsg());
}
}
5 异步事件:
Spring默认监控的事件都是同步的,实现异步事件就需要开启异步事件的支持,配置类上使用@EventListener注解开启异步支持,然后在监听器上使用@Async注解标注即可,同一个事件多个处理器可以使用@Order注解进行排序(参数越小优先级越高)
实现:
@Configuration
@EnableAsync
public class EventConfig {
@Async
@EventListener
public void doWithEvent(MyEvent myEvent) {
System.out.println("事件消息是: "+myEvent.getMsg());
}
}
@Async//配置类已经开启异步支持
@Component
public class EventHandler implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
//todo----
System.out.println(event.getMsg());
}
}
6 事件异常处理器(事件消费方出现异常进行必要处理)
(1) 同步的:
编写异常处理器实现 org.springframework.util.ErrorHandler
import org.springframework.stereotype.Component;
import org.springframework.util.ErrorHandler;
//同步方式异常处理器
@Component
public class DoExphandler implements ErrorHandler {
/**
* 只要在SimpleApplicationEventMulticaster设置这个异常处理器,
* 事件消费方抛出异常就会触发这个方法中的异常,SimpleApplicationEventMulticaster.setErrorHandler(exphandler);
*/
@Override
public void handleError(Throwable e) {
if (e instanceof RuntimeException) {
//todo
} else {
}
}
}
在SimpleApplicationEventMulticaster事件广播中设置消费事的异常处理器
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class EventProduceService implements ApplicationContextAware, ApplicationEventPublisherAware {
//实现方式一
private ApplicationContext applicationContext;
//实现方式二
private ApplicationEventPublisher applicationEventPublisher;
//事件推送类注入广播处理同步异常
@Autowired
private SimpleApplicationEventMulticaster saem;
@Autowired
private DoExphandler exphandler;
/**
* 容器初始化时候会自动的填装该对象
*
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 容器初始化时候会自动的填装该对象
*
* @param applicationEventPublisher
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void sentEvent2(Object msg) {
applicationContext.publishEvent(new MyEvent2((String) msg));
}
/**
* 设置初始化的事件异常处理器
*/
@PostConstruct
public void init(){
saem.setErrorHandler(exphandler);
}
}
(2)异步的:
编写异步事件处理器异常类,实现AsyncUncaughtExceptionHandler接口
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex,
Method method,
Object... params) {
//todo,做相关处理
ex.printStackTrace();
}
}
做异步事件异常配置:
实现AsyncConfigurer接口
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import java.util.concurrent.Executor;
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Autowired
private AsyncExceptionHandler asyncExceptionHandler;
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return asyncExceptionHandler;
}
@Override
public Executor getAsyncExecutor() {
System.out.println("getAsyncExecutor");
return AsyncConfigurer.super.getAsyncExecutor();
}
}
7 java自带的事件:
(1)观察者模式:
作用: 解耦,解耦....其他都是废话
模式工作思想: a观察b,b做出某些动作后,a就及时的做动作的跟进(至于a做啥,看你需要他做啥)
设计思想:a根据b的状态变化做出响应,一般情况下都是多个对象观察一个对象,此时被观察者b就需要感知到都有哪些对象在观察自己(设置集合存储这些对象)
观察者:(在java.util.Observer已经做了顶层接口)
public interface MyObserver {
void update(ObserverHandler handler);
}
class MyObserverImp implements MyObserver{
private int status;
/**
* 根据被观察者对象适应自身动作
* @param handler 被观察者对象
*/
@Override
public void update(ObserverHandler handler) {
status=((Handler)handler).getStatus();
}
被观察者:(java.util. Observable已经做了适应)
interface ObserverHandler {
//存储观察者,感知都有那些对象在观察
List<MyObserver> list = new ArrayList<>();
}
class Handler implements ObserverHandler {
private int status;
public void setStatus(int status) {
this.status = status;
updateAllStatus();
}
public int getStatus() {
return status;
}
public void updateAllStatus() {
for (MyObserver myObserver : list) {
myObserver.update(this);
}
}
public void addObserver(MyObserver observer) {
list.add(observer);
}
public void removeObserver(MyObserver observer) {
list.remove(observer);
}
}
(2)java的事件:
创建事件继承java.util.EventObject
public class UserEvent extends EventObject {
public UserEvent(Object source) {
super(source);
}
}
class SendMessageEvent extends UserEvent {
public SendMessageEvent(Object source) {
super(source);
}
}
class SendFileEvent extends UserEvent {
public SendFileEvent(Object source) {
super(source);
}
}
创建事件监听器继承:java.util.EventListener
interface UserListener extends EventListener {
static final ConcurrentHashMap<Object, Object> map = new ConcurrentHashMap<>();
void doWithEvent(UserEvent event);
}
class Listener implements UserListener {
@Override
public void doWithEvent(UserEvent event) {
if (event instanceof SendFileEvent) {
System.out.println(event);
} else if (event instanceof SendMessageEvent) {
System.out.println(event);
}
}
}
推送事件:
class SendEventHandler {
private static UserListener listener = new Listener();
public static void main(String[] args) {
final SendMessageEvent sentMessage = new SendMessageEvent("发送事件");
final SendFileEvent sendFile = new SendFileEvent("发送文件");
listener.doWithEvent(sentMessage);
listener.doWithEvent(sendFile);
}
}