使用net.jodah.failsafe能否执行Function<T,R>?有更优雅的适配方案吗?
Failsafe 带参带返回值方法执行方案
Failsafe 官方没有提供直接执行Function类型任务的API,但无需修改原有业务类的结构,通过Lambda表达式包装就能实现需求,比你目前的方案优雅得多,还能避免线程安全问题。
最优方案:Lambda捕获参数适配Supplier
你完全不需要修改原有MyClass的代码,直接在调用Failsafe时用Lambda把带参方法包装成Supplier即可,Lambda会自动捕获作用域内的参数:
// 原有类无需任何改动 class MyClass { public Integer methodThatWillBeCalledWithFailsafe(String str) { //do something return retVal; } } // 调用侧代码示例 MyClass myClass = new MyClass(); String input = "你要传入的参数"; // 这里的() -> 就是把带参调用包装成无参的Supplier Integer result = Failsafe.with(yourRetryPolicy) .get(() -> myClass.methodThatWillBeCalledWithFailsafe(input));
该方案的优势:
- 不需要修改原有业务方法的签名和结构,没有侵入性
- 不存在线程安全问题:每次调用生成的Supplier独立持有对应参数,多线程场景下复用同一个MyClass实例也不会互相干扰
- 编码简洁,没有额外的对象开销
进阶封装:通用Function执行工具
如果你需要频繁调用不同的带参方法,也可以封装通用工具方法来适配:
/** * 通用Failsafe执行Function的工具方法 * @param function 要执行的带参方法 * @param param 方法入参 * @param retryPolicy 你配置的Failsafe策略 * @return 方法返回值 */ public <P, R> R runFunctionWithFailsafe(Function<P, R> function, P param, RetryPolicy<R> retryPolicy) { return Failsafe.with(retryPolicy) .get(() -> function.apply(param)); } // 调用示例 Integer result = runFunctionWithFailsafe( myClass::methodThatWillBeCalledWithFailsafe, "测试参数", yourRetryPolicy );
原方案的弊端说明
你之前把入参存为类私有字段的方案存在明显的线程安全隐患:如果多个线程同时调用同一个MyClass实例的方法,私有字段会被不同线程修改,导致逻辑错误。如果每次调用都新建MyClass实例,又会产生不必要的对象创建开销,完全没必要用这种实现方式。
内容的提问来源于stack exchange,提问作者Igor_M
相关产品推荐
相关产品推荐

