前言
前一節,我們了解了Spring 提供的 Aware接口,我們可以通過這個實作這個接口的一些類擷取到我們需要的東西。具體内容見前一節。 Spring 也提供了一種單機的事件機制。可以通過發送、監聽,來實作一些異步操作。 使用這種 類似 MQ 的事件機制,我們可以通過 這個事件機制來完成一些自己的業務操作。在我們使用spring提供的事件機制時,我們隻需要關注自己的事件,和自己的事件處理器。所有的事件都會繼承 ApplicationEvent,然後再完成對于自己時間的監聽器,監聽器都 實作 ApplicationListener接口,實作 onApplicationEvent方法,來處理監聽到的事件。 下面是事件注冊、監聽的整體過程。主要就是 在spring容器加載的時候,把所有的監聽器統一注冊到SimpleApplicationEventMulticaster事件分發器中,然後統一處理。
實作
ApplicationEvent 事件基類, EventObject是java提供的一個類
public 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系統事件
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(ApplicationContext source) {
super(source);
}
public final ApplicationContext getApplicationContext() {
return (ApplicationContext) getSource();
}
}
複制代碼
ApplicationEventPublisher 事件釋出器,統一釋出事件。
public interface ApplicationEventPublisher {
/**
* 釋出事件
* @param event 事件
*/
void publishEvent(ApplicationEvent event);
}
複制代碼
ApplicationEventMulticaster事件管理、分發器。ApplicationEventMulticaster統一定義公共行為, AbstractApplicationEventMulticaster抽象類處理公共邏輯。SimpleApplicationEventMulticaster預設分發器,隻需要執行具體的分發邏輯。supportEvent方法檢查事件是否需要被處理。
public interface ApplicationEventMulticaster {
/**
* Add a listener to be notified of all events.
* @param listener the listener to add
*/
void addApplicationListener(ApplicationListener listener);
/**
* Remove a listener from the notification list.
* @param listener the listener to remove
*/
void removeApplicationListener(ApplicationListener listener);
/**
* Multicast the given application event to appropriate listeners.
* @param event the event to multicast
*/
void multicastEvent(ApplicationEvent event);
}
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
private final Set<ApplicationListener> applicationListeners = new LinkedHashSet<>();
private BeanFactory beanFactory;
@Override
public void addApplicationListener(ApplicationListener listener) {
this.applicationListeners.add((ApplicationListener) listener);
}
@Override
public void removeApplicationListener(ApplicationListener listener) {
this.applicationListeners.remove(listener);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) throws BeansException {
LinkedList<ApplicationListener<?>> allListeners = new LinkedList<>();
for (ApplicationListener<?> listener : applicationListeners) {
if (supportEvent(listener, event)) {
allListeners.add(listener);
}
}
return allListeners;
}
/**
* 監聽器是否對該事件感興趣
*/
protected boolean supportEvent(ApplicationListener listener, ApplicationEvent event) throws BeansException {
// 檢查事件是否需要關注
Class<? extends ApplicationListener> clazz = listener.getClass();
Class<?> targetClass = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
Type genericInterface = targetClass.getGenericInterfaces()[0];
Type typeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
String className = typeArgument.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());
}
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster{
@Override
public void multicastEvent(ApplicationEvent event) {
try {
// 實作事件處理
Collection<ApplicationListener<?>> listeners = getApplicationListeners(event);
for (ApplicationListener listener : listeners) {
listener.onApplicationEvent(event);
}
}catch (Exception e){
// 執行失敗
}
}
}
複制代碼
AbstractApplicationContext容器重新整理,完成 事件分發器的注冊、事件監聽器的注冊。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
private ApplicationEventMulticaster applicationEventMulticaster;
/**
* 模闆方法,控制定義spring上下文的重新整理與建立
* @throws BeansException
*/
@Override
public void refresh() throws BeansException {
// 1. 建立beanFactory,加載beanDefinition
refreshBeanFactory();
// 2. 擷取 beanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3. 添加 ApplicationContextAwareProcessor,讓繼承自 ApplicationContextAware 的 Bean 對象都能感覺所屬的 ApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 4. bean 執行個體化之前 執行 beanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 5. beanPostProcessor 完成 bean 執行個體化後的注冊操作
registerBeanPostProcessors(beanFactory);
// 6. 提前執行個體化 單例bean 對象
beanFactory.preInstantiateSingletons();
// 初始化事件釋出者
initApplicationEventMulticaster();
// 注冊監聽事件
registerListeners();
// 完成重新整理
finishRefresh();
}
private void finishRefresh() {
publishEvent(new ContextRefreshedEvent(this));
}
private void registerListeners() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
Collection<ApplicationListener> listeners = beanFactory.getBeansOfType(ApplicationListener.class).values();
for (ApplicationListener listener : listeners) {
applicationEventMulticaster.addApplicationListener(listener);
}
}
private void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
applicationEventMulticaster = new SimpleApplicationEventMulticaster();
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
}
@Override
public void publishEvent(ApplicationEvent event) {
applicationEventMulticaster.multicastEvent(event);
}
}
複制代碼
測試
定義事件、定義事件監聽器。
/**
* @author huangle
* @date 2023/3/14 16:21
*/
public class ConsumerEvent extends ApplicationContextEvent {
private String msgId;
private String msgBody;
public ConsumerEvent(ApplicationContext source, String msgId, String msgBody) {
super(source);
this.msgId = msgId;
this.msgBody = msgBody;
}
}
public class ConsumerEventLister implements ApplicationListener<ConsumerEvent> {
@Override
public void onApplicationEvent(ConsumerEvent consumerEvent) {
System.out.println(this.getClass()+"接受到消息:"+consumerEvent.getMsgId()+"-"+consumerEvent.getMsgBody());
}
}
複制代碼
注入事件監聽器
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="consumerEventLister" class="cn.anoxia.springframework.beans.factory.support.event.ConsumerEventLister"/>
<bean id="applicationRefershEventListener" class="cn.anoxia.springframework.beans.factory.support.event.ApplicationRefershEventListener"/>
<bean id="applicationCloseEventListener" class="cn.anoxia.springframework.beans.factory.support.event.ApplicationCloseEventListener"/>
</beans>
複制代碼
釋出事件
@Test
public void testEvent() throws BeansException{
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.publishEvent(new ConsumerEvent(applicationContext, UUID.randomUUID().toString(),"消息發送成功!"));
applicationContext.registerShutdownHook();
}
複制代碼
作者:Anoxia1
連結:https://juejin.cn/post/7225891176532770877