Spring中有个event事件,可以提供事件的定义、监听和发布事件操作,此次事件监听发布的实现采用的是观察者模式,这种一个地方发布了事件,需要另一个地方立刻监听感知到比较适合观察者模式,实现完毕,我们自定义实现的事件可以在spring生命周期里进行定义,监听发布。
在此种实现中,需要设计出事件定义,对事件的监听,以及对事件的发布,对事件的发布需要广播器进行处理等等,程序的入口,需要用到之前都一直在用的上下文刷新类AbstractApplicationContext的refresh(),用它初始化事件广播器,并发布一些刷新事件和关闭容器等事件,接下来咱们开始把
1.工程目录
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─spring
│ │ │ └─sourcecode
│ │ │ │ SourcecodeApplication.java
│ │ │ │
│ │ │ └─springframework
│ │ │ │ BeanDefinition.java
│ │ │ │ BeanFactory.java
│ │ │ │
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ Aware.java
│ │ │ │ │ BeanClassLoaderAware.java
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ BeanFactoryAware.java
│ │ │ │ │ BeanNameAware.java
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ DisposableBean.java
│ │ │ │ │ FactoryBean.java
│ │ │ │ │ HierarchicalBeanFactory.java
│ │ │ │ │ InitializingBean.java
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ │ DisposableBeanAdapter.java
│ │ │ │ │ FactoryBeanRegistrySupport.java
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java
│ │ │ │
│ │ │ ├─context
│ │ │ │ │ ApplicationContext.java
│ │ │ │ │ ApplicationContextAware.java
│ │ │ │ │ ApplicationEvent.java
│ │ │ │ │ ApplicationEventPublisher.java
│ │ │ │ │ ApplicationListener.java
│ │ │ │ │ ConfigurableApplicationContext.java
│ │ │ │ │
│ │ │ │ ├─event
│ │ │ │ │ AbstractApplicationEventMulticaster.java
│ │ │ │ │ ApplicationContextEvent.java
│ │ │ │ │ ApplicationEventMulticaster.java
│ │ │ │ │ ContextClosedEvent.java
│ │ │ │ │ ContextRefreshedEvent.java
│ │ │ │ │ SimpleApplicationEventMulticaster.java
│ │ │ │ │
│ │ │ │ └─supprot
│ │ │ │ AbstractApplicationContext.java
│ │ │ │ AbstractRefreshableApplicationContext.java
│ │ │ │ AbstractXmlApplicationContext.java
│ │ │ │ ApplicationContextAwareProcessor.java
│ │ │ │ ClassPathXmlApplicationContext.java
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java
│ │ │ │ DefaultResourceLoader.java
│ │ │ │ FileSystemResource.java
│ │ │ │ Resource.java
│ │ │ │ ResourceLoader.java
│ │ │ │ UrlResource.java
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java
│ │ │
│ │ └─resources
│ │ application.properties
│ │ spring.xml
│ │
│ └─test
│ └─java
│ └─com
│ └─spring
│ └─sourcecode
│ │ SourcecodeApplicationTests.java
│ │
│ └─springframework
│ │ ApiTest.java
│ │
│ └─test
│ └─event
│ ContextClosedEventListener.java
│ ContextRefreshedEventListener.java
│ CustomEvent.java
│ CustomEventListener.java
│
2.xml类图
1.ApplicationEvent
所有事件定义的父类,对于ContextRefreshedEvent来说就是刷新事件,对于ContextClosedEvent来说就是关闭事件的定义,就是用来对事件的定义
2.ApplicationListener事件监听器
ApplicationListener是个接口,当你想要实现刷新容器时进行监听可定义刷新监听器在进行实现ApplicationListener此接口,可用来自定义监听
3.ApplicationEventMulticaster
此接口是事件广播器,主要定义几个功能,用来注册事件监听器到容器里,从容器里删除监听器, 将给定的事件多播到对应发布出去
4.ApplicationEventPublisher
事件发布的定义接口,实现类里主要是用广播器发布出去
3.代码实现
?ApplicationEvent类,继承EventObject,主要是jdk自带的事件的父类
package com.spring.sourcecode.springframework.context;
import java.util.EventObject;
/**
* @Author df
* @Date 2022/5/8 18:55
* @Version 1.0
*
* 抽象应用事件类
*/
public abstract class ApplicationEvent extends EventObject {
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public ApplicationEvent(Object source) {
// 调用父类的构造方法
super(source);
}
}
ApplicationContextEvent
package com.spring.sourcecode.springframework.context.event;
import com.spring.sourcecode.springframework.context.ApplicationContext;
import com.spring.sourcecode.springframework.context.ApplicationEvent;
/**
* @Author df
* @Date 2022/5/8 19:00
* @Version 1.0
*
*/
public class ApplicationContextEvent extends ApplicationEvent {
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public ApplicationContextEvent(Object source) {
super(source);
}
/*public final ApplicationContext getApplicationContext() {
return (ApplicationContext) getSource();
}*/
}
ContextClosedEvent
package com.spring.sourcecode.springframework.context.event;
/**
* @Author df
* @Date 2022/5/8 20:11
* @Version 1.0
* // 具体的事件定义
*/
public class ContextClosedEvent extends ApplicationContextEvent {
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public ContextClosedEvent(Object source) {
super(source);
}
}
ContextRefreshedEvent
package com.spring.sourcecode.springframework.context.event;
/**
* @Author df
* @Date 2022/5/8 20:12
* @Version 1.0
*/
public class ContextRefreshedEvent extends ApplicationContextEvent {
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public ContextRefreshedEvent(Object source) {
super(source);
}
}
ApplicationEventMulticaster:定义事件广播器
package com.spring.sourcecode.springframework.context.event;
import com.spring.sourcecode.springframework.context.ApplicationEvent;
import com.spring.sourcecode.springframework.context.ApplicationListener;
/**
* @Author df
* @Date 2022/5/8 20:54
* @Version 1.0
*/
// 事件广播器
public interface ApplicationEventMulticaster {
// 添加要通知所有事件的监听器
void addApplicationListener(ApplicationListener<?> listener);
// 从通知列表中删除监听器
void removeApplicationListener(ApplicationListener<?> listener);
// 将给定的应用程序事件多播到适当的监听器
void multicastEvent(ApplicationEvent applicationEvent);
}
AbstractApplicationEventMulticaster:定义抽象类实现ApplicationEventMulticaster类的部分实现,如addApplicationListener和removeApplicationListener。此类中还定义了getApplicationListeners(),主要是获取容器中所有的监听器是否符合你给定的监听事件,符合的进行返回,并调用对应的监听实现。
package com.spring.sourcecode.springframework.context.event;
import com.spring.sourcecode.springframework.beans.BeansException;
import com.spring.sourcecode.springframework.beans.factory.BeanFactory;
import com.spring.sourcecode.springframework.beans.factory.BeanFactoryAware;
import com.spring.sourcecode.springframework.context.ApplicationEvent;
import com.spring.sourcecode.springframework.context.ApplicationListener;
import org.springframework.util.ClassUtils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;
/**
* @Author df
* @Date 2022/5/13 10:38
* @Version 1.0
*/
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {
private final Set<ApplicationListener<ApplicationEvent>> applicationListeners = new LinkedHashSet<>();
/* @Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}*/
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
applicationListeners.add((ApplicationListener<ApplicationEvent>) listener);
}
@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
applicationListeners.remove(listener);
}
// 摘取符合广播事件中的监听处理器,具体过滤动作在supportsEvent中
// 1.将所有的和ApplicationListener类有关系的都存储到应用事件容器里
// 2.比如在bean处理时刷新到容器中完成时,则刷新事件并发布刷新事件
// 3.这时将传过来的刷新事件与之前存储容器事件进行对比
// 4.对比成功以后就存储到list以后返回
// 循环容器中存储的监听事件和你要发布的事件是否一致
protected Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event) {
LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>();
for (ApplicationListener<ApplicationEvent> listener : applicationListeners) {
if (supportsEvent(listener, event)) allListeners.add(listener);
}
return allListeners;
}
/**
* 监听器是否对该事件感兴趣
*/
protected boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) {
Class<? extends ApplicationListener> listenerClass = applicationListener.getClass();
// 按照 CglibSubclassingInstantiationStrategy、SimpleInstantiationStrategy 不同的实例化类型,需要判断后获取目标 class
Class<?> targetClass = ClassUtils.isCglibProxyClass(listenerClass) ? listenerClass.getSuperclass() : listenerClass;
Type genericInterface = targetClass.getGenericInterfaces()[0];
Type actualTypeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
String className = actualTypeArgument.getTypeName();
Class<?> eventClassName;
try {
eventClassName = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new BeansException("wrong event class name: " + className);
}
// 判定此 eventClassName 对象所表示的类或接口与指定的 event.getClass() 参数所表示的类或接口是否相同,或是否是其超类或超接口。
// isAssignableFrom是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。
return eventClassName.isAssignableFrom(event.getClass());
}
}
SimpleApplicationEventMulticaster:此类继承AbstractApplicationEventMulticaster广播器,当是匹配的监听器,实现发布广播。
package com.spring.sourcecode.springframework.context.event;
import com.spring.sourcecode.springframework.beans.factory.BeanFactory;
import com.spring.sourcecode.springframework.context.ApplicationEvent;
import com.spring.sourcecode.springframework.context.ApplicationListener;
/**
* @Author df
* @Date 2022/5/13 10:58
* @Version 1.0
*/
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
// 调用实现的事件处理器
@Override
public void multicastEvent(final ApplicationEvent applicationEvent) {
for (final ApplicationListener listener : getApplicationListeners(applicationEvent)) {
listener.onApplicationEvent(applicationEvent);
}
}
}
ApplicationEventPublisher:事件发布定义
/**
* @Author df
* @Date 2022/5/13 10:46
* @Version 1.0
* // 事件发布者定义
*/
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}
AbstractApplicationContext部分实现,只添加本节添加的东西,添加了初始化广播器
以及注册事件监听器,发布刷新容器,和关闭容器
@Override
public void refresh() {
// 6.
initApplicationEventMulticaster();
// 7.注册事件监听器
registerListeners();
// 8.提前实例化单例bean对象
// 通过beanDefinationMap里的实例对象将后续bean实例进行实例化,并处理后置修改的对象
beanFactory.preInstantiateSingletons();
// 9. 发布容器刷新完成事件
finishRefresh();
}
private void initApplicationEventMulticaster() {
//ConfigurableListableBeanFactory beanFactory = getBeanFactory();
applicationEventMulticaster = new SimpleApplicationEventMulticaster();
//beanFactory
}
// 将配置文件的关于监听的配置进行注册存储容器里
private void registerListeners() {
Collection<ApplicationListener> applicationListeners = getBeansOfType(ApplicationListener.class).values();
for (ApplicationListener listener : applicationListeners) {
applicationEventMulticaster.addApplicationListener(listener);
}
}
private void finishRefresh() {
publishEvent(new ContextRefreshedEvent(this));
}
@Override
public void publishEvent(ApplicationEvent event) {
applicationEventMulticaster.multicastEvent(event);
}
@Override
public void close() {
// 发布容器关闭事件
publishEvent(new ContextClosedEvent(this));
getBeanFactory().destroySingletons();
}
4.测试准备
4.1 创建一个自定义事件和监听器
package com.spring.sourcecode.springframework.test.event;
import com.spring.sourcecode.springframework.context.event.ApplicationContextEvent;
/**
* @Author df
* @Date 2022/5/13 11:24
* @Version 1.0
*/
public class CustomEvent extends ApplicationContextEvent {
private Long id;
private String message;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public CustomEvent(Object source, Long id, String message) {
super(source);
this.id = id;
this.message = message;
}
// 省略set/get
}
自定义事件监听器
package com.spring.sourcecode.springframework.test.event;
import com.spring.sourcecode.springframework.context.ApplicationListener;
import java.util.Date;
/**
* @Author df
* @Date 2022/5/13 11:27
* @Version 1.0
*/
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
System.out.println("收到:" + event.getSource() + "消息;时间:" + new Date());
System.out.println("消息:" + event.getId() + ":" + event.getMessage());
}
}
4.2 创建一个容器刷新事件监听器
package com.spring.sourcecode.springframework.test.event;
import com.spring.sourcecode.springframework.context.ApplicationListener;
import com.spring.sourcecode.springframework.context.event.ContextRefreshedEvent;
/**
* @Author df
* @Date 2022/5/13 11:52
* @Version 1.0
*/
public class ContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("刷新事件");
}
}
4.3 创建一个事件关闭监听处理器
package com.spring.sourcecode.springframework.test.event;
import com.spring.sourcecode.springframework.context.ApplicationListener;
import com.spring.sourcecode.springframework.context.event.ContextRefreshedEvent;
/**
* @Author df
* @Date 2022/5/13 11:52
* @Version 1.0
*/
public class ContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("刷新事件");
}
}
4.4 配置文件,将几个监听器配置进来
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean class="com.spring.sourcecode.springframework.test.event.CustomEventListener">
</bean>
<bean class="com.spring.sourcecode.springframework.test.event.ContextClosedEventListener">
</bean>
<bean class="com.spring.sourcecode.springframework.test.event.ContextRefreshedEventListener">
</bean>
</beans>
4.5 单元测试
public class ApiTest {
//
@Test
public void testFactoryBean() {
// 1.初始化BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.publishEvent(new CustomEvent(applicationContext, 1019129009086763L, "成功了!"));
applicationContext.registerShutdownHook();
}
}
5.测试结果
?
|