通用库自定义异常适配问题:多仓库不同异常类复用
最优通用配置方案
以下是几种无需逐个方法传参的通用解决方案,按解耦程度和可维护性排序:
1. 依赖注入+异常工厂模式
定义统一的异常工厂接口,让两个仓库各自实现该接口,通用库仅依赖接口生成异常,完全隔离具体异常类的耦合。
通用库代码
// 通用库中定义异常工厂接口 public interface ExceptionFactory { RuntimeException create(String message); RuntimeException create(String message, Throwable cause); } // 通用库业务类,通过构造器注入工厂 public class CommonBusinessService { private final ExceptionFactory exceptionFactory; public CommonBusinessService(ExceptionFactory exceptionFactory) { this.exceptionFactory = exceptionFactory; } public void validateParam(String param) { if (param == null || param.isBlank()) { throw exceptionFactory.create("参数不能为空"); } } }
仓库实现代码
Recruit仓库提供自己的工厂实现:
public class RecruitExceptionFactory implements ExceptionFactory { @Override public RuntimeException create(String message) { return new RecruitException(message); } @Override public RuntimeException create(String message, Throwable cause) { return new RecruitException(message, cause); } } // 初始化通用库组件时传入工厂 CommonBusinessService service = new CommonBusinessService(new RecruitExceptionFactory());
Developer仓库同理,实现DeveloperExceptionFactory即可。
2. SPI服务自动发现机制
利用语言自带的SPI(服务提供者接口)机制,让通用库在启动时自动加载对应仓库的异常工厂实现,无需手动注入。
通用库代码
复用上面的ExceptionFactory接口,新增加载器:
public class ExceptionFactoryLoader { public static ExceptionFactory get() { ServiceLoader<ExceptionFactory> loader = ServiceLoader.load(ExceptionFactory.class); return loader.findFirst().orElseThrow(() -> new IllegalStateException("未找到异常工厂实现")); } } // 通用库业务类直接使用加载器获取工厂 public class CommonBusinessService { private final ExceptionFactory exceptionFactory = ExceptionFactoryLoader.get(); public void doBusiness() { if (someError) { throw exceptionFactory.create("业务执行失败"); } } }
仓库配置
在Recruit仓库的META-INF/services目录下创建文件com.yourpackage.ExceptionFactory,内容为:
com.recruit.RecruitExceptionFactory
Developer仓库同理,创建对应文件并写入自己的工厂类全限定名。
3. 类路径检测动态生成异常
如果不想引入工厂类,可通过检测类路径中存在的异常类,动态反射创建实例,适合简单场景。
通用库代码
public class ExceptionCreator { private static Class<? extends RuntimeException> targetException; static { try { // 优先检测RecruitException targetException = Class.forName("com.recruit.RecruitException").asSubclass(RuntimeException.class); } catch (ClassNotFoundException e) { try { // 检测失败则加载DeveloperException targetException = Class.forName("com.developer.DeveloperException").asSubclass(RuntimeException.class); } catch (ClassNotFoundException ex) { throw new IllegalStateException("未找到指定异常类"); } } } public static RuntimeException create(String message) { try { return targetException.getConstructor(String.class).newInstance(message); } catch (Exception e) { throw new RuntimeException("创建异常失败", e); } } } // 通用库业务类使用 public class CommonBusinessService { public void processData() { if (dataInvalid) { throw ExceptionCreator.create("数据格式无效"); } } }
注意事项
需确保两个异常类的构造方法签名完全一致(比如都有String参数的构造器)。
内容的提问来源于stack exchange,提问作者Yash Mittal
相关产品推荐
相关产品推荐

