Java中如何将同一接口多实现生成级联调用函数,有无现成工具类?
现有开源实现说明
Apache Commons Lang 3.10及以上版本提供的FunctionalUtils工具类已经覆盖了大部分场景的级联调用需求:
- 针对JDK内置的无返回值
Consumer、有返回值Function等函数式接口,提供了andThen系列方法,可直接将多个同类型实现拼接为级联调用的新实例 - 该工具类也支持1~3个入参的自定义函数式接口级联,能满足绝大多数业务使用需求
如果需要完全适配任意参数数量、任意返回类型的自定义函数式接口,可直接基于JDK动态代理实现通用级联工具,无需引入额外依赖。
通用级联工具实现
以下是可直接使用的通用实现,完美解决你提到的两个问题:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.function.BinaryOperator; public class CascadeUtils { /** * 无返回值场景级联,按传入顺序执行所有实现的接口方法 * @param functionalInterface 要级联的函数式接口类 * @param implementations 同接口的多个实现实例 * @return 级联后的接口实例 */ @SuppressWarnings("unchecked") public static <T> T cascade(Class<T> functionalInterface, T... implementations) { if (!functionalInterface.isInterface() || !functionalInterface.isAnnotationPresent(FunctionalInterface.class)) { throw new IllegalArgumentException("仅支持函数式接口的级联"); } if (implementations == null || implementations.length == 0) { throw new IllegalArgumentException("至少需要传入一个实现实例"); } return (T) Proxy.newProxyInstance( functionalInterface.getClassLoader(), new Class[]{functionalInterface}, (proxy, method, args) -> { for (T impl : implementations) { method.invoke(impl, args); } // void返回类型场景JDK会自动忽略返回的null return null; } ); } /** * 有返回值场景级联,按传入顺序执行所有实现,用reducer聚合返回结果 * @param functionalInterface 要级联的函数式接口类 * @param reducer 返回值聚合函数,入参为前一个执行结果和当前执行结果 * @param implementations 同接口的多个实现实例 * @return 级联后的接口实例 */ @SuppressWarnings("unchecked") public static <T, R> T cascade(Class<T> functionalInterface, BinaryOperator<R> reducer, T... implementations) { if (!functionalInterface.isInterface() || !functionalInterface.isAnnotationPresent(FunctionalInterface.class)) { throw new IllegalArgumentException("仅支持函数式接口的级联"); } if (implementations == null || implementations.length == 0 || reducer == null) { throw new IllegalArgumentException("参数不能为空,且至少需要传入一个实现实例"); } return (T) Proxy.newProxyInstance( functionalInterface.getClassLoader(), new Class[]{functionalInterface}, (proxy, method, args) -> { R result = (R) method.invoke(implementations[0], args); for (int i = 1; i < implementations.length; i++) { R current = (R) method.invoke(implementations[i], args); result = reducer.apply(result, current); } return result; } ); } }
使用示例
无返回值场景(对应你最初的需求)
public SomeInterface getFunction() { // 直接传入接口类和所有实现即可 return CascadeUtils.cascade(SomeInterface.class, imp1, imp2, imp3); }
调用返回的SomeInterface实例时,会自动按顺序执行imp1、imp2、imp3的call方法,和你手写lambda的效果完全一致。
有返回值场景
public void hoge() { SomeInterface i = (a, b, c) -> a; SomeInterface j = (a, b, c) -> b; SomeInterface k = (a, b, c) -> c; // 传入返回值聚合规则,此处取最后一个实现的返回值 SomeInterface all = CascadeUtils.cascade(SomeInterface.class, (prevRes, currRes) -> currRes, i, j, k); // 调用all.call(1,2,3)会返回最后一个实现的结果3 }
方案优势
- 支持任意参数数量的函数式接口,无需针对参数个数单独写适配代码
- 两个重载方法分别适配void和有返回值场景,无需额外兼容处理
- 直接使用业务自定义的接口即可,不需要额外定义通用函数式接口
- 动态代理的性能开销极低,常规业务场景下完全可以忽略
内容的提问来源于stack exchange,提问作者jjskriii
相关产品推荐
相关产品推荐

