Spring Boot 优雅回调工具类 LambdaSafe

前言

发现了 Spring Boot 一个处理回调的工具类,做个分享

LambdaSafe

LambdaSafeCallback

	/**
	 * 回调处理基类
	 */
	protected abstract static class LambdaSafeCallback<C, A, SELF extends LambdaSafeCallback<C, A, SELF>> {

		// 回调类型
		private final Class<C> callbackType;

		// 被回调实例
		private final A argument;

		private Log logger;

		// 过滤器,默认 GenericTypeFilter
		private Filter<C, A> filter = new GenericTypeFilter<>();

		LambdaSafeCallback(Class<C> callbackType, A argument, Object[] additionalArguments) {
			this.callbackType = callbackType;
			this.argument = argument;
			this.additionalArguments = additionalArguments;
			this.logger = LogFactory.getLog(callbackType);
		}

		// logger 构造器
		public SELF withLogger(Class<?> loggerSource) {
			return withLogger(LogFactory.getLog(loggerSource));
		}
		// logger 构造器
		public SELF withLogger(Log logger) {
			this.logger = logger;
			return self();
		}

		// filter 构造器
		SELF withFilter(Filter<C, A> filter) {
			this.filter = filter;
			return self();
		}

		// InvocationResult:封装回调接口(如果有的话)
		protected final <R> InvocationResult<R> invoke(C callbackInstance, Supplier<R> supplier) {

			// 如果过滤器通过(泛型匹配)就执行回调
			if (this.filter.match(this.callbackType, callbackInstance, this.argument, this.additionalArguments)) {
				try {
					return InvocationResult.of(supplier.get());
				}
				catch (ClassCastException ex) {
					// ...
				}
			}
			return InvocationResult.noResult();
		}

		// ...

	}
  • 回调处理的抽象基类 LambdaSafeCallback,这是一个内部类(高内聚的体现)
  • 主要是 invoke 逻辑,它在执行回调方法前会经过 Filter 的过滤,默认实例是 GenericTypeFilter

Callback

	public static final class Callback<C, A> extends LambdaSafeCallback<C, A, Callback<C, A>> {

		private final C callbackInstance;

		// 私有构造
		private Callback(Class<C> callbackType, C callbackInstance, A argument, Object[] additionalArguments) {
			super(callbackType, argument, additionalArguments);
			this.callbackInstance = callbackInstance;
		}

		// 指定回调 Consumer,没有返回值
		public void invoke(Consumer<C> invoker) {
			invoke(this.callbackInstance, () -> {
				invoker.accept(this.callbackInstance);
				return null;
			});
		}

		// ...

	}
  • LambdaSafeCallback 的内部类实现
  • 构造方法私有化,由 LambdaSafe 暴露出去,见后文
  • 指定对应的 Consumer,由 super.invoke 调用,Consumer 就对应的回调逻辑比如 Costomizer::costumize

Callbacks

	// Callback 的复数版本
	public static final class Callbacks<C, A> extends LambdaSafeCallback<C, A, Callbacks<C, A>> {

		private final Collection<? extends C> callbackInstances;

		private Callbacks(Class<C> callbackType, Collection<? extends C> callbackInstances, A argument,
				Object[] additionalArguments) {
			super(callbackType, argument, additionalArguments);
			this.callbackInstances = callbackInstances;
		}

		// ...

	}
  • Callback 的复数版本,Spring 常用的设计模式,可以理解为 组合模式(composite)

Filter

	@FunctionalInterface
	interface Filter<C, A> {

		/**
		 * 基于回调器类型、回调器实例、被回调实例解析过滤
		 */
		boolean match(Class<C> callbackType, C callbackInstance, A argument, Object[] additionalArguments);

		/**
		 * 静态方法,提供一个 all true 的实例
		 */
		static <C, A> Filter<C, A> allowAll() {
			return (callbackType, callbackInstance, argument, additionalArguments) -> true;
		}

	}
  • 内部类函数式接口
  • 主要是对回调方法的执行进行过滤

GenericTypeFilter

	// 对泛型的匹配过滤
	private static class GenericTypeFilter<C, A> implements Filter<C, A> {

		@Override
		public boolean match(Class<C> callbackType, C callbackInstance, A argument, Object[] additionalArguments) {

			// 解析对应回调器上指定的泛型
			ResolvableType type = ResolvableType.forClass(callbackType, callbackInstance.getClass());

			// 如果指定了泛型则解析出来必须与被回调类一致
			if (type.getGenerics().length == 1 && type.resolveGeneric() != null) {
				return type.resolveGeneric().isInstance(argument);
			}

			return true;
		}

	}
  • Filter 接口的内部类实现
  • 主要逻辑就是对 泛型 的校验,比如 Customizer<Specific> 指定了处理回调的类型为 Specific,则传入的 argument 类型就必须是 Specific,如果没指定或者制定了多个泛型等,默认返回 true

LambdaSafe

	// 返回一个 Callback 实例
	public static <C, A> Callback<C, A> callback(Class<C> callbackType, C callbackInstance, A argument,
			Object... additionalArguments) {
		return new Callback<>(callbackType, callbackInstance, argument, additionalArguments);
	}

	// 返回一个 Callbacks 实例
	public static <C, A> Callbacks<C, A> callbacks(Class<C> callbackType, Collection<? extends C> callbackInstances,
			A argument, Object... additionalArguments) {
		return new Callbacks<>(callbackType, callbackInstances, argument, additionalArguments);
	}
  • 基于前面的铺垫,LambdaSafe 暴露静态方法用于获取对应的 Callback Callbacks 实例
  • 具体回调逻辑基于 invoke 方法实现

示例

Customizer

@FunctionalInterface
public interface Customizer<T> {

    void customize(T instance);

}

很眼熟的 Customizer 回调处理类,对 T 类型的实例进行回调处理

HelloService

public class HelloService {

    public void callback() {
        System.out.println("hello");
    }

}

被回调测试类,回调方法为 callback

TestMain

public class TestMain {

    @Test
    public void test() {
        HelloService instance = new HelloService();
        Customizer<HelloService> customizer = HelloService::callback;

        // 必须指定正确的泛型与 instance 匹配
        // Customizer<LambdaSafe> customizer = t -> {};

        LambdaSafe.callback(
                Customizer.class
                , customizer
                , instance
                , null
        )
                .invoke(customizer1 -> customizer1.customize(instance));
    }
}

基于 LambdaSafe.Callback 实例的优雅回调

Spring Boot 使用案例

public class CacheManagerCustomizers {

	// 所有用户注册的 CacheManagerCustomizer
	private final List<CacheManagerCustomizer<?>> customizers;

	public CacheManagerCustomizers(List<? extends CacheManagerCustomizer<?>> customizers) {
		this.customizers = (customizers != null) ? new ArrayList<>(customizers) : Collections.emptyList();
	}

	@SuppressWarnings("unchecked")
	// 基于 LambdaSafe.Callbacks 的优雅回调
	public <T extends CacheManager> T customize(T cacheManager) {
		LambdaSafe.callbacks(CacheManagerCustomizer.class, this.customizers, cacheManager)
				.withLogger(CacheManagerCustomizers.class).invoke((customizer) -> customizer.customize(cacheManager));
		return cacheManager;
	}

}
  • 这是 Spring BootSpring Cache 的自动装配支持
  • 此类会基于用户注册的所有 CacheManagerCustomizer 对容器中的 cacheManager 实例进行回调处理
  • 使用了 LambdaSafe.Callbacks 的优雅回调

总结

Spring Boot 大佬封装的小而美的工具类,用起来

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值