概要
今天在阅读MallChat的业务代码的时候,发现在事务模块中有个自动配置类TransactionAutoConfiguration。当中有一段代码从来没有见过,故此记录一下写法以及其中使用到的一些技术方法。
整体架构流程
附上代码
/**
* Collect any {@link AsyncConfigurer} beans through autowiring.
*/
@Autowired
void setConfigurers(ObjectProvider<SecureInvokeConfigurer> configurers) {
Supplier<SecureInvokeConfigurer> configurer = SingletonSupplier.of(() -> {
List<SecureInvokeConfigurer> candidates = configurers.stream().collect(Collectors.toList());
if (CollectionUtils.isEmpty(candidates)) {
return null;
}
if (candidates.size() > 1) {
throw new IllegalStateException("Only one SecureInvokeConfigurer may exist");
}
return candidates.get(0);
});
executor = Optional.ofNullable(configurer.get()).map(SecureInvokeConfigurer::getSecureInvokeExecutor).orElse(ForkJoinPool.commonPool());
}
可以看到这个方法是设置配置使用。传入的参数ObjectProvider < SecureInvokeConfigurer > configurers为从IOC容器中获取。在方法中将参数处理赋值给executor线程池。泛型中的类为自定义接口,有且仅有一个方法,返回值为一个线程池。
public interface SecureInvokeConfigurer {
/**
* 返回一个线程池
*/
@Nullable
default Executor getSecureInvokeExecutor() {
return null;
}
}
查看实现发现只有一个线程池配置类实现了这个接口
可以看到实现getSecureInvokeExecutor方法返回了mallchatExecutor()方法。
@Bean(MALLCHAT_EXECUTOR)
@Primary
public ThreadPoolTaskExecutor mallchatExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("mallchat-executor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//满了调用线程执行,认为重要任务
executor.setThreadFactory(new MyThreadFactory(executor));
executor.initialize();
return executor;
}
可以看出mallchatExecutor方法就是返回了一个自定义的线程池。这个方法使用了@Primary注解,查询资料得知这个注解是用于在多个相同类型的 bean 中指定一个默认的 bean。
兜了一圈相当于最开始setConfigurers方法的参数为ioc容器中的ThreadPoolConfig配置类。
方法内主要就是使用了SingletonSupplier.of(Supplier< T> supplier)这个方法。这个方法也是头一次遇见,应该是函数式接口Supplier那边相关的方法。看类名应该是和单例有关系。
下面附上SingletonSupplier的源码。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.util.function;
import java.util.function.Supplier;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
public class SingletonSupplier<T> implements Supplier<T> {
@Nullable
private final Supplier<? extends T> instanceSupplier;
@Nullable
private final Supplier<? extends T> defaultSupplier;
@Nullable
private volatile T singletonInstance;
public SingletonSupplier(@Nullable T instance, Supplier<? extends T> defaultSupplier) {
this.instanceSupplier = null;
this.defaultSupplier = defaultSupplier;
this.singletonInstance = instance;
}
public SingletonSupplier(@Nullable Supplier<? extends T> instanceSupplier, Supplier<? extends T> defaultSupplier) {
this.instanceSupplier = instanceSupplier;
this.defaultSupplier = defaultSupplier;
}
private SingletonSupplier(Supplier<? extends T> supplier) {
this.instanceSupplier = supplier;
this.defaultSupplier = null;
}
private SingletonSupplier(T singletonInstance) {
this.instanceSupplier = null;
this.defaultSupplier = null;
this.singletonInstance = singletonInstance;
}
@Nullable
public T get() {
T instance = this.singletonInstance;
if (instance == null) {
synchronized(this) {
instance = this.singletonInstance;
if (instance == null) {
if (this.instanceSupplier != null) {
instance = this.instanceSupplier.get();
}
if (instance == null && this.defaultSupplier != null) {
instance = this.defaultSupplier.get();
}
this.singletonInstance = instance;
}
}
}
return instance;
}
public T obtain() {
T instance = this.get();
Assert.state(instance != null, "No instance from Supplier");
return instance;
}
public static <T> SingletonSupplier<T> of(T instance) {
return new SingletonSupplier(instance);
}
@Nullable
public static <T> SingletonSupplier<T> ofNullable(@Nullable T instance) {
return instance != null ? new SingletonSupplier(instance) : null;
}
public static <T> SingletonSupplier<T> of(Supplier<T> supplier) {
return new SingletonSupplier(supplier);
}
@Nullable
public static <T> SingletonSupplier<T> ofNullable(@Nullable Supplier<T> supplier) {
return supplier != null ? new SingletonSupplier(supplier) : null;
}
}
可以看出这个类实现了Supplier接口。里面有三个属性
@Nullable
//包装的真正的Supplier
private final Supplier<? extends T> instanceSupplier;
@Nullable
//默认的Supplier
private final Supplier<? extends T> defaultSupplier;
@Nullable
//包装的实例
private volatile T singletonInstance;
看到有两个of方法,一个参数是Supplier的,相当于把instanceSupplier传进来,一个是T的,相当于直接把实例singletonInstance传进来,然后调构造方法给属性赋值。
主要就是get()方法。可以看出逻辑主要就是DCL单例模式。
@Nullable
public T get() {
T instance = this.singletonInstance;
if (instance == null) {
synchronized(this) {
instance = this.singletonInstance;
if (instance == null) {
if (this.instanceSupplier != null) {
instance = this.instanceSupplier.get();
}
if (instance == null && this.defaultSupplier != null) {
instance = this.defaultSupplier.get();
}
this.singletonInstance = instance;
}
}
}
return instance;
}
首先就是DCL加锁判断包装实例是否为空,不为空就直接返回实例,为空就去调用instanceSupplier的get方法将结果赋值给singletonInstance。如果singletonInstance还未空并且默认的defaultSupplier不为空就调用defaultSupplier的get方法。
小结
本质上setConfigurers方法就是获取到IOC中的ThreadPoolConfig,然后将ThreadPoolConfig中的getSecureInvokeExecutor方法返回的线程池赋值给executor。如果没有则默认使用用ForkJoinPool.commonPool()返回的线程池。