如何用Java编写异常工厂
我们目前正在开发一个内部使用的框架。我们现在要使用标准化的异常ID和消息。开发人员只需提供一个ID和一条默认消息,框架就会查找相关消息(如果可能)或使用默认消息(如果无法检索消息)。 第一个想法是编写一个异常工厂,强制开发人员提供错误ID,然后在工厂方法中查找消息。这种方法的问题是,在stacktrace(创建异常的工厂方法)中添加了一个额外的帧。那不太好。几乎每一个试图隐藏创造的解决方案都有这个问题。 第二个想法是将消息查找和我们的异常类耦合起来,并编写一个抽象异常类,该类接受构造函数中的错误ID并处理消息查找。但这也不是很好,因为它缺少松耦合。 第三个想法是让开发人员每次都编写消息的查找。。也很糟糕 你有什么想法吗 另外,我想这是我第一次需要Java中的宏 代码中的不同方法: 一, 或 二, 三,如何用Java编写异常工厂,java,exception,frameworks,factory,Java,Exception,Frameworks,Factory,我们目前正在开发一个内部使用的框架。我们现在要使用标准化的异常ID和消息。开发人员只需提供一个ID和一条默认消息,框架就会查找相关消息(如果可能)或使用默认消息(如果无法检索消息)。 第一个想法是编写一个异常工厂,强制开发人员提供错误ID,然后在工厂方法中查找消息。这种方法的问题是,在stacktrace(创建异常的工厂方法)中添加了一个额外的帧。那不太好。几乎每一个试图隐藏创造的解决方案都有这个问题。 第二个想法是将消息查找和我们的异常类耦合起来,并编写一个抽象异常类,该类接受构造函数中的错误
可以编辑堆栈跟踪,删除不需要的元素。如果所有异常的构造函数都需要相同的数据,请使用单个createException,否则请使用createCustomException方法 这将删除不必要的堆栈跟踪元素
public static <T extends Throwable> T adjustStackTrace(T ex, int removedElements) {
//use an explicit constraint for removedElements
if (removedElements < 1) {
throw new IllegalArgumentException("removedElements may not be less than 1");
}
final StackTraceElement[] stack = ex.getStackTrace();
//or an implicit constraint
removedElements = Math.max(removedElements, stack.length);
final StackTraceElement[] newStack = new StackTraceElement[stack.length - removedElements];
System.arraycopy(stack, removedElements, newStack, 0, stack.length - removedElements);
ex.setStackTrace(newStack);
return ex;
}
或者,您可以使用单个方法并传递所需的异常类:
public Exception createException(Class<?> exClass, Object... someExceptionSpecificData) {...}
此示例基于来自oval框架的net.sf.oval.internal.util.Assert,请参见如何创建错误消息工厂而不是异常工厂?
public TechnicalException(ErrorId errorId, String defaultmsg) {
super(defaultmsg);
//get msg here and set on a new field cause detailMessage is not accessible. Also overwrite toString();
}
throw new TechnicalException(new ErrorId("123"), "defaultmsg");
ErrorId errorId = new ErrorId("123");
String msg = someProvider.getMessage(errorId);
throw new TechnicalException(errorId, msg);
public static <T extends Throwable> T adjustStackTrace(T ex, int removedElements) {
//use an explicit constraint for removedElements
if (removedElements < 1) {
throw new IllegalArgumentException("removedElements may not be less than 1");
}
final StackTraceElement[] stack = ex.getStackTrace();
//or an implicit constraint
removedElements = Math.max(removedElements, stack.length);
final StackTraceElement[] newStack = new StackTraceElement[stack.length - removedElements];
System.arraycopy(stack, removedElements, newStack, 0, stack.length - removedElements);
ex.setStackTrace(newStack);
return ex;
}
public static TechnicalException createTechnicalException(Object... someExceptionSpecificData) {
StringBuilder sb = new StringBuilder();
sb.append("...").append("..."); //create a message
//process the someExceptionSpecificData
Object[] someNewData = someExceptionSpecificData;
TechnicalException ex = new TechnicalException(sb.toString(), someNewData);
ex = adjustStackTrace(ex, 1 /*remove StackTraceElement, related to this method call*/);
return ex;
}
public Exception createException(Class<?> exClass, Object... someExceptionSpecificData) {...}
public void useExceptionFactory() {
throw ExceptionFactory.createTechnicalException();
}
public void adjustEvenMore() {
//adjust even more to hide the implementation of your library
throw ExceptionFactory.adjustStackTrace(ExceptionFactory.createTechnicalException(),1);
}