spring源码解析-(4)Spring中的事件

创建消息事件

public class UserEvent extends ApplicationEvent {
	private static final long serialVersionUID = 1L;
	public UserEvent(Object source) {
		super(source);
	}
}

创建事件监听器

public class UserListener implements ApplicationListener<UserEvent> {
	@Override
	public void onApplicationEvent(UserEvent event) {
		System.out.println(event);
	}
}

测试类

// 创建一个监听类
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
// 添加监听器
simpleApplicationEventMulticaster.addApplicationListener(new UserListener());
// 执行事件
simpleApplicationEventMulticaster.multicastEvent(new UserEvent("hello world"));

事件源码解析

首先我们可以从SimpleApplicationEventMulticaster看到如下的源码,从源码中可以看出,事件不仅仅可以添加多个事件处理器,还可以添加线程池和异常处理器。

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

   @Nullable
   private Executor taskExecutor;

   @Nullable
   private ErrorHandler errorHandler;
    // 其他方法省略
}

接下来我们可以查看其父类的源码AbstractApplicationEventMulticaster

public abstract class AbstractApplicationEventMulticaster
		implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
	// 真正的监听器的检索器
	private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
	// 缓存监听器
	final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
}

看一看是如何进行缓存的,那为什么要分开存储呢?

我们可以从存储的内容去思考,非单例的类会产生多个实例,那如果我每个都缓存,势必会造成浪费,而且我还需要去处理它的生命周期,还不如直接存储其名称,在使用的时候根据名称去获取到对应的实例

而单例顾名思义:有且仅有一个,所以我可以将它缓存,他的生命周期随着项目的生命周期存活,这个既避免了重复创建的问题,还可以保持效率。

private class CachedListenerRetriever {
    // 用于存储单列和lambda的监听器
    @Nullable
    public volatile Set<ApplicationListener<?>> applicationListeners;
    // 用于存储非单例的bean名称
    @Nullable
    public volatile Set<String> applicationListenerBeans;
}

添加事件的流程

从下面代码可以看出,如果你配置了线程池,多个事件是并发执行的,如果线程池为null,则会在当前线程串行执行。

@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);
        }
    }
}

因为我们并没有配置线程池,所以直接跳转到invokeListener方法中,此方法中,我们可以看出事件的异常处理补偿机制,我们之后在处理一些可能遇到异常的情况,也可以参考这种写法去完善一些补偿机制。

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);
    }
}

完整版测试类

// 创建一个事件发布器
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
simpleApplicationEventMulticaster.addApplicationListener(new UserListener());
simpleApplicationEventMulticaster.addApplicationListener(new OrderListener());
// 创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
simpleApplicationEventMulticaster.setTaskExecutor(executorService);
// 创建一个异常处理机制
simpleApplicationEventMulticaster.setErrorHandler(err -> {
System.out.println(err.getMessage());
});
simpleApplicationEventMulticaster.multicastEvent(new UserEvent("hello world"));
simpleApplicationEventMulticaster.multicastEvent(new OrderEvent("hello world"));
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值