Spring中的观察者模式
- 发布的事件,Event,ApplicationEvent是一个抽象类继承了EventObject,EventObject是JDK中的类,所有的事件类都建议继承自EventObject。
public abstract class ApplicationEvent extends EventObject{}
- 事件监听器,ApplicationListener是一个接口,该接口继承了EventListener接口。EventListener接口是JDK中的接口,所有的事件监听器都建议继承EventListener接口。
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {}
- 事件发布,ApplicationEventPublisher,ApplicationContext继承该接口,并在抽象实现类AbstractApplicationContext中做了实现。
applicationContext.publishEvent(new FileParseEvent(this, streamBean));
AbstractApplicationContext类中publishEvent方法实现:
/**
* Publish the given event to all listeners.
* @param event the event to publish (may be an {@link ApplicationEvent}
* or a payload object to be turned into a {@link PayloadApplicationEvent})
* @param eventType the resolved event type, if known
* @since 4.2
*/
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 事件发布委托getApplicationEventMulticaster来执行
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
ApplicationEventMulticaster的multicastEvent方法的实现在SimpleApplicationEventMulticaster类中:
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 获得监听器集合,遍历监听器
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
这就执行了了onApplicationEvent方法,这里是事件发生的地方。
spring如何根据事件找到对应的监听器
再spring容器初始化的时候,也就是refresh方法中
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
......
try {
......
// Initialize event multicaster for this context.
//初始化一个事件注册表
initApplicationEventMulticaster();
......
// Check for listener beans and register them.
//注册事件监听器
registerListeners();
......
}
}
}
initApplicationEventMulticaster方法初始化事件注册表:
protected void initApplicationEventMulticaster() {
//获得beanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//先查找BeanFactory中是否有ApplicationEventMulticaster
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {//如果BeanFactory中不存在,就创建一个SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
在AbstractApplicationEventMulticaster类中有如下属性:
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
// 注册表
private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
// 注册表缓存
final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
@Nullable
private ClassLoader beanClassLoader;
@Nullable
private ConfigurableBeanFactory beanFactory;
DefaultListenerRetriever 的结构如下:
private class DefaultListenerRetriever {
// 用来存放监听事件
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
// 存放监听事件的类名称
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
初始化注册表之后,就会把事件注册到注册表中,registerListeners():
protected void registerListeners() {
//获取所有的Listener,把事件的bean放到ApplicationEventMulticaster中
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
//把事件的名称放到ApplicationListenerBean里去。
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
Spring使用反射机制,通过方法getBeansOfType获取所有继承了ApplicationListener接口的监听器,然后把监听器放到注册表中,所以我们可以在Spring配置文件中配置自定义监听器,在Spring初始化的时候,会把监听器自动注册到注册表中去。
例:
要发布的事件:
@Getter
@Setter
public class FileParseEvent extends ApplicationEvent {
private StreamBean streamBean;
/**
* Create a new {@code ApplicationEvent}.
*
* @param source the object on which the event initially occurred or with
* which the event is associated (never {@code null})
*/
public FileParseEvent(Object source, StreamBean streamBean) {
super(source);
this.streamBean = streamBean;
}
}
事件发布的动作
applicationContext.publishEvent(new FileParseEvent(this, streamBean));
处理事件
@Slf4j
@Component
public class FileParseListener implements ApplicationListener<FileParseEvent> {
@Async
@Override
public void onApplicationEvent(FileParseEvent event) {
// 具体处理代码
}
}