一、【spring事件】相关
1.观察者模式【行为型模式】
-
1.1、定义
- 又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
-
1.2结构
在观察者模式中有如下角色:
- Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
- ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
- Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
- ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
-
1.3、优缺点
1,优点:
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
- 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】
2,缺点:
- 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
- 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃
-
1.4、使用场景
- 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
- 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时。
2、适配器模式(结构型模式)
- 2.1、定义
- 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
- 2.2、结构
- 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
- 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
- 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
ctrl+shift+alt+n:全局查找器查找所有的类
3、spring事件
3.1、事件监听的3种方式
-
1、实现 ApplicationListener 接口
- 根据接口泛型确定事件类型
相关代码
// 事件解耦例子 @Configuration public class A48_1 { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_1.class); context.getBean(MyService.class).doBusiness(); context.close(); } static class MyEvent extends ApplicationEvent { public MyEvent(Object source) { super(source); } } @Component static class MyService { private static final Logger log = LoggerFactory.getLogger(MyService.class); @Autowired private ApplicationEventPublisher publisher; // applicationContext 具体主题角色类 public void doBusiness() { log.debug("主线业务"); // 主线业务完成后需要做一些支线业务,下面是问题代码 publisher.publishEvent(new MyEvent("MyService.doBusiness()")); } } //具体主题角色类 @Component static class SmsApplicationListener implements ApplicationListener<MyEvent> { private static final Logger log = LoggerFactory.getLogger(SmsApplicationListener.class); @Override public void onApplicationEvent(MyEvent event) { log.debug("发送短信"); } } @Component static class EmailApplicationListener implements ApplicationListener<MyEvent> { private static final Logger log = LoggerFactory.getLogger(EmailApplicationListener.class); @Override public void onApplicationEvent(MyEvent event) { log.debug("发送邮件"); } } }
-
2、@EventListener 标注监听方法
-
根据监听器方法参数确定事件类型
-
解析时机:在 SmartInitializingSingleton(所有单例初始化完成后),解析每个单例 bean
@Configuration public class A48_2 { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_2.class); context.getBean(MyService.class).doBusiness(); context.close(); } static class MyEvent extends ApplicationEvent { public MyEvent(Object source) { super(source); } } @Component static class MyService { private static final Logger log = LoggerFactory.getLogger(MyService.class); @Autowired private ApplicationEventPublisher publisher; // applicationContext public void doBusiness() { log.debug("主线业务"); // 主线业务完成后需要做一些支线业务,下面是问题代码 publisher.publishEvent(new MyEvent("MyService.doBusiness()")); } } @Component static class SmsService { private static final Logger log = LoggerFactory.getLogger(SmsService.class); @EventListener public void listener(MyEvent myEvent) { log.debug("发送短信"); } } @Component static class EmailService { private static final Logger log = LoggerFactory.getLogger(EmailService.class); @EventListener public void listener(MyEvent myEvent) { log.debug("发送邮件"); } } //设置多线程 @Bean public ThreadPoolTaskExecutor executor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(3); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); return executor; } @Bean public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolTaskExecutor executor) { SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster(); multicaster.setTaskExecutor(executor); return multicaster; } }
可以设置多线程实现异步监听
-
-
3、自定义注解实现监听
package com.example.springevent.a48; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author: liang * @DATE: 2023/1/3 * @PACKAGE_NAME: com.example.springevent.a48 * @NAME: A48_3 * @PROJECT_NAME: 自定义注解 **/ @Configuration public class A48_3 { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class); context.getBean(MyService.class).doBusiness(); context.close(); } /** * * 单例初始化后被调用 * @param context * @return */ @Bean public SmartInitializingSingleton smartInitializingSingleton(ConfigurableApplicationContext context){ return new SmartInitializingSingleton(){ @Override public void afterSingletonsInstantiated() { for (String name : context.getBeanDefinitionNames()) { Object bean = context.getBean(name); //获取方法对象 for (Method method : bean.getClass().getMethods()) { //判断方法对象是否存在MyListener注解,适配器模式 if (method.isAnnotationPresent(MyListener.class)) { ApplicationListener listener = new ApplicationListener<ApplicationEvent>() { @Override public void onApplicationEvent(ApplicationEvent event) { System.out.println(event); //监听器方法需要的事件类型 Class<?> eventType = method.getParameterTypes()[0]; if (eventType.isAssignableFrom(event.getClass())){ try { method.invoke(bean,event); } catch (Exception e) { e.printStackTrace(); } } }; }; //将listener加入到监听器中,让context知道 context.addApplicationListener(listener); } } } } }; } @Component static class MyService { private static final Logger log = LoggerFactory.getLogger(MyService.class); @Autowired private ApplicationEventPublisher publisher; // applicationContext public void doBusiness() { log.debug("主线业务"); // 主线业务完成后需要做一些支线业务,下面是问题代码 publisher.publishEvent(new MyEvent("MyService.doBusiness()")); } } @Component static class SmsService { private static final Logger log = LoggerFactory.getLogger(SmsService.class); @MyListener public void listener(MyEvent myEvent) { log.debug("发送短信"); } } @Component static class EmailService { private static final Logger log = LoggerFactory.getLogger(EmailService.class); @MyListener public void listener(MyEvent myEvent) { log.debug("发送邮件"); } } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface MyListener { } static class MyEvent extends ApplicationEvent { public MyEvent(Object source) { super(source); } } }
3.2、事件发布器
事件发布器模拟实现
- addApplicationListenerBean 负责收集容器中的监听器
- 监听器会统一转换为 GenericApplicationListener 对象,以支持判断事件类型
- multicastEvent 遍历监听器集合,发布事件
- 发布前先通过 GenericApplicationListener.supportsEventType 判断支持该事件类型才发事件
- 可以利用线程池进行异步发事件优化
- 如果发送的事件对象不是 ApplicationEvent 类型,Spring 会把它包装为 PayloadApplicationEvent 并用泛型技术解析事件对象的原始类型
- 视频中未讲解
@Configuration
public class A49 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A49.class);
context.getBean(MyService.class).doBusiness();
context.close();
}
static class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
@Component
static class MyService {
private static final Logger log = LoggerFactory.getLogger(MyService.class);
@Autowired
private ApplicationEventPublisher publisher; // applicationContext
public void doBusiness() {
log.debug("主线业务");
// 主线业务完成后需要做一些支线业务,下面是问题代码
publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
}
}
@Component
static class SmsApplicationListener implements ApplicationListener<MyEvent> {
private static final Logger log = LoggerFactory.getLogger(SmsApplicationListener.class);
@Override
public void onApplicationEvent(MyEvent event) {
log.debug("发送短信");
}
}
@Component
static class EmailApplicationListener implements ApplicationListener<MyEvent> {
private static final Logger log = LoggerFactory.getLogger(EmailApplicationListener.class);
@Override
public void onApplicationEvent(MyEvent event) {
log.debug("发送邮件");
}
}
@Bean
public ThreadPoolTaskExecutor executor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
return executor;
}
@Bean
public ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext context, ThreadPoolTaskExecutor executor){
return new AbstractApplicationEventMulticaster() {
private List<GenericApplicationListener> listeners = new ArrayList<>();
//收集监听器
@Override
public void addApplicationListenerBean(String name) {
ApplicationListener listener = context.getBean(name, ApplicationListener.class);
//获取该监听器支持的事件类型
ResolvableType type = ResolvableType.forClass(listener.getClass()).getInterfaces()[0].getGeneric();
System.out.println("type = " + type);
//将原始的listener封装为支持事件检查的listener
GenericApplicationListener genericApplicationListener = new GenericApplicationListener() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
listener.onApplicationEvent(event);
}
//判断是否支持某事件类型
@Override
public boolean supportsEventType(ResolvableType eventType) {
//判断eventType是否能赋值给type
return type.isAssignableFrom(eventType);
}
};
listeners.add(genericApplicationListener);
}
//发布事件
@Override
public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
for (GenericApplicationListener listener : listeners) {
if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
listener.onApplicationEvent(event);
}
}
}
};
}
abstract static class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
}
@Override
public void addApplicationListenerBean(String listenerBeanName) {
}
@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
}
@Override
public void removeApplicationListenerBean(String listenerBeanName) {
}
@Override
public void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate) {
}
@Override
public void removeApplicationListenerBeans(Predicate<String> predicate) {
}
@Override
public void removeAllListeners() {
}
@Override
public void multicastEvent(ApplicationEvent event) {
}
@Override
public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
}
}
}