1

我正在开发一个包含几个模块的项目。我想在每个模块中提供一个自定义异常的能力,该异常从带有自定义error_code-error_message对的属性文件中静态填充内部结构,例如HashMap。我有一个包含静态属性的基本抽象自定义异常:

public abstract class AbstractException extends RuntimeException{
   public static Map<String, String> ERRORS = new HashMap<String, String>();
   public String code;
   // getters and setter for code ommited

   public static init(String fileName, Class<?> clazz){
    // read properties file
    // populate map
   }

   public static String getMessageByCode(String code){
    //
   String mess = ERRORS.get(code);
   // in case of null message provide default message about unknown error
   }

   public AbstractException(String code){
      super(getMessageByCode(code));
      this.setCode(code);
   }

   public AbstractException(Throwable thr){
      super(getMessageByCode("ERROR_999"), thr);
      this.setCode(code);
   }

   public AbstractException(Throwable thr, String msg){
      super(getMessageByCode("ERROR_999") + " " + msg, thr);
      this.setCode(code);
   }

}

简单的自定义异常

public class MyException extends AbstractException{
 static{
   // populate internal map with module-specific errors
   init("module1.errors.properties", MyException.class);
 }     

public MyException(String code){
 super(getMessageByCode());
}
// rest code omited

}

代码中自定义异常的简单用法:

throw new MyException("ERROR_404");

问题我可以在这段代码中看到:

  1. ERRORS 映射存在于抽象异常的所有子类中
  2. 并发访问静态 ERRORS 字段。

问题是,如何避免这些问题,可能有人对我的问题有更好的解决方案?

4

1 回答 1

1

这种设计行不通,因为只有一个 的副本ERRORS,在所有子类之间共享。一种可能的解决方案是 ExceptionFactory,它管理各种ERRORS映射并可以为您创建所需子类的异常。例如

public static class AbstractException extends RuntimeException 
{ 
    String code;
    String message;
    public void setCode(String code) { this.code = code; }
    public void setMessage(String message) { this.message = message; }
}

public static class MyException1 extends AbstractException{ }

public static class MyException2 extends AbstractException{ }

public static class ExceptionFactory
{
    private Map<Class<?>,Map<String,String>> errorMaps = new HashMap<Class<?>, Map<String,String>>();
    public void register(Class<? extends AbstractException> exType, String fileName)
    {
        Map<String,String> errors = new HashMap<String,String>();
        // load errors from fileName
        errorMaps.put(exType, errors);
    }

    public <T extends AbstractException> T newException(Class<T> exType, String code)
    {
        Map<String,String> map = errorMaps.get(exType);
        String message = map.get(code);
        T ex;
        try
        {
            ex = exType.newInstance();
            ex.setCode(code);
            ex.setMessage(message);
            return ex;
        }
        catch(InstantiationException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch(IllegalAccessException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
于 2011-07-15T14:47:20.630 回答