Как определить сигнатуру метода динамически при создании пользовательских исключений? - PullRequest
0 голосов
/ 27 августа 2018

Я следую стандарту, который требует от меня регистрации метода class #, который создает исключение для легкой отладки из нашего пользовательского интерфейса. Не извлекая логи, я знаю, какой метод породил исключение и может (обычно) легко найти основную причину.

Однако я бы хотел динамический способ определения сигнатуры метода, потому что в настоящее время я жестко его кодирую везде, где выкидываю исключение. Есть ли лучший способ.

 @Service
 public class UserService {

     @Autowired
     private UserRepository userRepository;

     public User findUser(Long id){

          if(id == null || id < 1){
               throw new BadRequestException("UserService#findUser", String.format(
                                             "Invalid Id: %d", id));
          }

          User user = userRepository.findOne(id);

          if(user == null){
               throw new DataNotFoundException("UserService#findUser", String.format(
                                               "Can't Find User for Id: %d", id));
          }
          return user;
     }
 }

-

Цель состоит в том, чтобы я мог создать любое пользовательское исключение, и в этом конструкторе я могу вывести сигнатуру метода, по которой было создано исключение.

 public BadRequestException(String issue){
      super(String.format("%s | Bad Request | %s", <<signature>>, issue);
 }

-

 UserService class --> findUser method --> BadRequest("UserService#findUser")
 UserService class --> createUser method --> BadRequest("UserService#createUser")

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Вы можете ввести вспомогательный метод, который извлекает метод и имена классов из текущего потока:

private static MethodAndClassName retrieveMethodAndClassName() {
       StackTraceElement[] allStackTraces = Thread.currentThread().getStackTrace();
       StackTraceElement currentMethod = allStackTraces[2]; 
       return new MethodAndClassName(currentMethod.getMethodName(), currentMethod.getClassName());      
}

Обратите внимание, что вызовы методов сложены. Я получаю третий последний вложенный вызов (allStackTraces[2]), потому что последний вызов (allStackTraces[0]) - Thread.getStackTrace(), предыдущий последний вызов (allStackTraces[1]) - retrieveMethodAndClassName() и предыдущий перед последним вызовом (allStackTraces[2]) это то, что вы ищете: метод, который вызвал retrieveMethodAndClassName().

MethodAndClassName - это пользовательский класс, который определяет необходимую информацию для трассировки:

public class MethodAndClassName {

    private String method;
    private String clazz;

    public MethodAndClassName(String method, String clazz) {
        this.method = method;
        this.clazz = clazz;
    }

    public String getMethodName() {
        return method;
    }

    public String getClassName() {
        return clazz;
    }
}

А в вашем клиентском коде используйте его, например:

 public User findUser(Long id){

      if(id == null || id < 1){             
           throw new BadRequestException(ReflectionHelper.retrieveMethodAndClassName(), String.format(
                                         "Invalid Id: %d", id));
      }

      User user = userRepository.findOne(id);

      if(user == null){
           throw new DataNotFoundException(ReflectionHelper.retrieveMethodAndClassName(), String.format(
                                           "Can't Find User for Id: %d", id));
      }
      return user;
 }
0 голосов
/ 27 августа 2018

Используйте Throwable.getStackTrace (). Это вернет массив StackTraceElement, и первая запись укажет, где был создан экземпляр Throwable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...