如何处理解耦?什么是事件?如何使用事件功能?
设计:观察者模式,实现 Spring Event 容器时间和事件监听器。
AbstractApplicationContext#refresh()
,以便于处理事件初始化和注册事件监听器的操作。AbstractApplicationContext
中添加相关事件内容。
isAssignableFrom
进行判断。isAssignableFrom
和 instanceof
相似,不过 isAssignableFrom
是用来判断子类和父类的关系的,或者接口的实现类和接口的关系。
Object
。A.isAssignableFrom(B)
结果是 true,证明 B 可以转换成 A,也就是 A 可以由 B 转换而来。spring-step-10
|-src
|-main
| |-java
| |-com.lino.springframework
| |-beans
| | |-factory
| | | |-config
| | | | |-AutowireCapableBeanFactory.java
| | | | |-BeanDefinition.java
| | | | |-BeanFactoryPostProcessor.java
| | | | |-BeanPostProcessor.java
| | | | |-BeanReference.java
| | | | |-ConfigurableBeanFactory.java
| | | | |-SingletonBeanRegistry.java
| | | |-support
| | | | |-AbstractAutowireCapableBeanFactory.java
| | | | |-AbstractBeabDefinitionReader.java
| | | | |-AbstractBeabFactory.java
| | | | |-BeabDefinitionReader.java
| | | | |-BeanDefinitionRegistry.java
| | | | |-CglibSubclassingInstantiationStrategy.java
| | | | |-DefaultListableBeanFactory.java
| | | | |-DefaultSingletonBeanRegistry.java
| | | | |-DisposableBeanAdapter.java
| | | | |-FactoryBeanRegistrySupport.java
| | | | |-InstantiationStrategy.java
| | | | |-SimpleInstantiationStrategy.java
| | | |-support
| | | | |-XMLBeanDefinitionReader.java
| | | |-Aware.java
| | | |-BeanClassLoaderAware.java
| | | |-BeanFactory.java
| | | |-BeanFactoryAware.java
| | | |-BeanNameAware.java
| | | |-ConfigurableListableBeanFactory.java
| | | |-DisposableBean.java
| | | |-FactoryBean.java
| | | |-HierarcgicalBeanFactory.java
| | | |-InitializingBean.java
| | | |-ListableBeanFactory.java
| | |-BeansException.java
| | |-PropertyValue.java
| | |-PropertyValues.java
| |-context
| | |-event
| | | |-AbstractApplicationEventMulticaster.java
| | | |-ApplicationContextEvent.java
| | | |-ApplicationEventMulticaster.java
| | | |-ContextclosedEvent.java
| | | |-ContextRefreshedEvent.java
| | | |-SimpleApplicationEventMulticaster.java
| | |-support
| | | |-AbstractApplicationContext.java
| | | |-AbstractRefreshableApplicationContext.java
| | | |-AbstractXmlApplicationContext.java
| | | |-ApplicationContextAwareProcessor.java
| | | |-ClassPathXmlApplicationContext.java
| | |-ApplicationContext.java
| | |-ApplicationContextAware.java
| | |-ApplicationEvent.java
| | |-ApplicationEventPublisher.java
| | |-ApplicationListener.java
| | |-ConfigurableApplicationContext.java
| |-core.io
| | |-ClassPathResource.java
| | |-DefaultResourceLoader.java
| | |-FileSystemResource.java
| | |-Resource.java
| | |-ResourceLoader.java
| | |-UrlResource.java
| |-util
| | |-ClassUtils.java
|-test
|-java
|-com.lino.springframework.test
|-event
| |-CustomClosedEventListener.java
| |-CustomEvent.java
| |-CustomEventListener.java
| |-CustomRefreshedEventListener.java
|-ApiTest.java
|-resources
|-spring.xml
event
事件定义、发布、监听功能实现和把事件相关内容使用 AbstractApplicationContext#refresh
进行注册和处理操作。spring context
包为主,事件的实现也是在这个包下进行扩展的,当然也可以看出来目前所有的实现内容,仍然是以 IOC 为主。ApplicationEvent.java
package com.lino.springframework.context;
import java.util.EventObject;
/**
* @description: 定义事件抽象类
*/
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);
}
}
java.util.EventObject
定义出具备事件功能的抽象类 ApplicationEvent
,后续所有事件的类都需要继承这个类。ApplicationContextEvent.java
package com.lino.springframework.context.event;
import com.lino.springframework.context.ApplicationContext;
import com.lino.springframework.context.ApplicationEvent;
/**
* @description: 定义应用上下文事件实现类
*/
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);
}
/**
* 获取应用上下文
*
* @return 应用上下文
*/
public final ApplicationContext getApplicationContext() {
return (ApplicationContext) getSource();
}
}
ContextRefreshedEvent.java
package com.lino.springframework.context.event;
/**
* @description: 上下文刷新事件类
*/
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);
}
}
ContextClosedEvent.java
package com.lino.springframework.context.event;
/**
* @description: 上下文关闭事件类
*/
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);
}
}
ClassUtils.java
package com.lino.springframework.util;
/**
* @description: 类工具类
*/
public class ClassUtils {
/**
* 获取默认类加载器
*
* @return 类加载器
*/
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back to system class loader...
}
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = ClassUtils.class.getClassLoader();
}
return cl;
}
/**
* 判断类是否是cglib代理对象
*
* @param clazz 类
* @return 是否是cglib代理对象
*/
public static boolean isCglibProxyClass(Class<?> clazz) {
return (clazz != null && isCglibProxyClassName(clazz.getName()));
}
/**
* 判断类名是否符合cglib代理类命名
*
* @param className 类名
* @return 是否符合cglib代理类命名
*/
public static boolean isCglibProxyClassName(String className) {
return (className != null && className.contains("$$"));
}
}
cglib
代理对象和是否符合 cglib
代理名称的方法。ApplicationListener.java
package com.lino.springframework.context;
import java.util.EventListener;
/**
* @description: 事件监听器
* @author: lingjian
* @createDate: 2022/12/1 15:01
*/
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* 处理事件
*
* @param event 事件
*/
void onApplicationEvent(E event);
}
ApplicationEventMulticaster.java
package com.lino.springframework.context.event;
import com.lino.springframework.context.ApplicationEvent;
import com.lino.springframework.context.ApplicationListener;
/**
* @description: 事件广播器
*/
public interface ApplicationEventMulticaster {
/**
* 添加监听器
*
* @param listener 监听器
*/
void addApplicationListener(ApplicationListener<?> listener);
/**
* 删除监听器
*
* @param listener 监听器
*/
void removeApplicationListener(ApplicationListener<?> listener);
/**
* 广播事件
*
* @param event 事件
*/
void multicastEvent(ApplicationEvent event);
}
multicastEvent
。AbstractApplicationEventMulticaster.java
package com.lino.springframework.context.event;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.BeanFactory;
import com.lino.springframework.beans.factory.BeanFactoryAware;
import com.lino.springframework.context.ApplicationEvent;
import com.lino.springframework.context.ApplicationListener;
import com.lino.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;
/**
* @description: 事件广播器抽象类
*/
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
public final Set<ApplicationListener<ApplicationEvent>> applicationListeners = new LinkedHashSet<>();
private BeanFactory beanFactory;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
applicationListeners.add((ApplicationListener<ApplicationEvent>) listener);
}
@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
applicationListeners.remove(listener);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
/**
* 获取事件监听器
*
* @param event 事件
* @return 监听器列表
*/
protected Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event) {
LinkedList<ApplicationListener> allListeners = new LinkedList<>();
for (ApplicationListener<ApplicationEvent> listener : applicationListeners) {
if (supportsEvent(listener, event)) {
allListeners.add(listener);
}
}
return allListeners;
}
/**
* 监听器是否该事件感兴趣
*
* @param applicationListener 监听器
* @param event 事件
* @return 是否感兴趣
*/
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());
}
}
addApplicationListener
、removeApplicationListener
这样的通用方法。这里主要是对 getApplicationListeners
、supportsEvent
的处理。
getApplicationListeners
:主要是摘取符合广播事件中的监听处理器,具体过滤动作在 supportsEvent
方法中。supportsEvent
:
ParameterizedType
和 eventClassName
,方便最后确认是否为子类和父类的关系,以此证明此事件归这个符合的类处理。eventClassName
和 event.getClass()
在 isAssignableFrom
判断下为 true。CglibSubclassingInstantiationStrategy、SimpleInstantiationStrategy
可以尝试在 AbstractApplicationContext
类中更换验证。SimpleApplicationEventMulticaster.java
package com.lino.springframework.context.event;
import com.lino.springframework.beans.factory.BeanFactory;
import com.lino.springframework.context.ApplicationEvent;
import com.lino.springframework.context.ApplicationListener;
/**
* @description: 简单事件广播器
*/
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
setBeanFactory(beanFactory);
}
@SuppressWarnings("unchecked")
@Override
public void multicastEvent(final ApplicationEvent event) {
for (final ApplicationListener listener : getApplicationListeners(event)) {
listener.onApplicationEvent(event);
}
}
}
ApplicationEventPublisher.java
package com.lino.springframework.context;
/**
* @description: 事件发布者接口
*/
public interface ApplicationEventPublisher {
/**
* 发布事件
*
* @param event 事件
*/
void publishEvent(ApplicationEvent event);
}
ApplicationEventPublisher
是一个事件的发布接口,所有的事件都需要从这个接口发布出去。ApplicationContext.java
package com.lino.springframework.context;
import com.lino.springframework.beans.factory.HierarchicalBeanFactory;
import com.lino.springframework.beans.factory.ListableBeanFactory;
import com.lino.springframework.core.io.ResourceLoader;
/**
* @description: 应用上下文接口
*/
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory, ResourceLoader, ApplicationEventPublisher {
}
AbstractApplicationContext.java
package com.lino.springframework.context.support;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.ConfigurableListableBeanFactory;
import com.lino.springframework.beans.factory.config.BeanFactoryPostProcessor;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.context.ApplicationEvent;
import com.lino.springframework.context.ApplicationListener;
import com.lino.springframework.context.ConfigurableApplicationContext;
import com.lino.springframework.context.event.ApplicationEventMulticaster;
import com.lino.springframework.context.event.ContextClosedEvent;
import com.lino.springframework.context.event.ContextRefreshedEvent;
import com.lino.springframework.context.event.SimpleApplicationEventMulticaster;
import com.lino.springframework.core.io.DefaultResourceLoader;
import java.util.Collection;
import java.util.Map;
/**
* @description: 抽象应用上下文
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
private ApplicationEventMulticaster applicationEventMulticaster;
@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 实例化之前,执行 BeanFactoryPostProcess
invokeBeanFactoryPostProcessor(beanFactory);
// 5.BeanPostProcessor 需要提前与其他 Bean 对象实例化之前执行注册操作
registerBeanPostProcessor(beanFactory);
// 6.初始化事件发布者
initApplicationEventMulticaster();
// 7.注册事件监听器
registerListeners();
// 8.提前实例化单例 Bean 对象
beanFactory.preInstantiateSingletons();
// 9.发布容器刷新完成事件
finishRefresh();
}
...
private void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingletonBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
}
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));
// 执行销毁单例bean的销毁方法
getBeanFactory().destroySingletons();
}
}
AbstractApplicationContext#refresh
中,主要新增了 初始化事件发布者、注册事件监听器、发布容器刷新完成事件。三个方法用于处理事件操作。
initApplicationEventMulticaster
):主要用于实例化一个 SimpleApplicationEventMulticaster
,这是一个事件广播器。registerListeners
):通过 getBeansOfType
方法获取到所有从 spring.xml
中加载到的事件配置 Bean 对象。finishRefresh
):发布了第一个服务器启动完成后的事件,这个事件通过 publishEvent
发布出去,其实也就是调用了 applicationEventMulticaster.multicastEvent(event)
方法。close
):新增加了发布一个容器关闭事件。publishEvent(new ContextClosedEvent(this))
。CustomEvent.java
package com.lino.springframework.test.event;
import com.lino.springframework.context.event.ApplicationContextEvent;
/**
* @description: 自定义事件
*/
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;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
CustomEventListener.java
package com.lino.springframework.test.event;
import com.lino.springframework.context.ApplicationListener;
import java.util.Date;
/**
* @description: 自定义事件监听器
*/
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());
}
}
CustomEvent
事件的监听器,这里可以处理自定义操作。CustomRefreshedEventListener.java
package com.lino.springframework.test.event;
import com.lino.springframework.context.ApplicationListener;
import com.lino.springframework.context.event.ContextRefreshedEvent;
/**
* @description: 自定义事件刷新监听器
* @author: lingjian
* @createDate: 2022/12/1 15:48
*/
public class CustomRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("刷新事件:" + this.getClass().getName());
}
}
CustomClosedEventListener.java
package com.lino.springframework.test.event;
import com.lino.springframework.context.ApplicationListener;
import com.lino.springframework.context.event.ContextClosedEvent;
/**
* @description: 自定义事件关闭监听器
*/
public class CustomClosedEventListener implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
System.out.println("关闭事件:" + this.getClass().getName());
}
}
spring.xml
<beans>
<bean class="com.lino.springframework.test.event.CustomEventListener"/>
<bean class="com.lino.springframework.test.event.CustomRefreshedEventListener"/>
<bean class="com.lino.springframework.test.event.CustomClosedEventListener"/>
beans>
spring.xml
配置文件中,添加了三个事件监听器,监听刷新、监控自定义事件、监听关闭事件。ApiTest.java
@Test
public void test_event() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.publishEvent(new CustomEvent(applicationContext, 1019129009086763L, "成功监听到了"));
applicationContext.registerShutdownHook();
}
applicationContext
新增加的发布事件接口方法,发布一个自定义事件 CustomEvent,并传了相应的参数信息。测试结果
刷新事件:com.lino.springframework.test.event.CustomRefreshedEventListener$$EnhancerByCGLIB$$b3c3d48f
收到:com.lino.springframework.context.support.ClassPathXmlApplicationContext@4cdbe50f消息;时间:Thu Dec 01 17:07:43 CST 2022
消息:1019129009086763:成功监听到了
关闭事件:com.lino.springframework.test.event.CustomClosedEventListener$$EnhancerByCGLIB$$20578a33
BeanFactory
、工厂方法 FactoryBean
、策略模式访问资源、观察者模式 Event
。