Могу ли я перехватывать исключения нулевого указателя в методе, использующем Spring AOP? - PullRequest
1 голос
/ 09 февраля 2012

У нас есть несколько классов отчетов в формате pdf, которые после массового импорта архивных данных иногда генерируют исключения нулевого указателя, когда биты данных отсутствуют, например, thing.getOtherThing().getText(); не будет иметь OtherThing, и отчет будет опрокидываться.

На мой взгляд, у нас есть несколько вариантов

  1. Исправить данные - не очень понятно, какими должны быть данные в каждом случае, и в некоторых случаях это вопрос человеческого суждения
  2. Повсюду ставьте try / catch и перебрасывайте полезное исключение, чтобы всплывать перед пользователем - много работы и уродливый код, но полезный для пользователей
  3. Повсюду ставьте нулевые проверки - нет, спасибо
  4. Работать над кодом DAO, чтобы объединить / nvl в запросах и сгенерировать отчеты с N / A в пропущенных полях (или банках) - хорошо, но не очень полезно

Или ...мы можем что-то сделать с АОП здесь?Можно ли перехватить нульпоинтеры, выброшенные в определенных классах / методах?Какой уровень информации доступен, когда они перехвачены?Помните, что несколько мест в методе могут выдавать нулевые указатели: (

Спасибо.

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

AOP потенциально может помочь вам найти решение, но вам нужно принять меры до того, как будет сгенерировано исключение, потому что исключение приведет к потере слишком большого количества контекста выполнения. Во-первых, когда вы пишете thing.getOtherThing.getText(), является ли getOtherThing полем с нечетным именем или вызовом метода, из которого вы случайно пропустили скобки? Если это последнее, вы можете использовать Spring AOP для перехвата метода ( при условии, что thing на самом деле является компонентом). Если нет, вам понадобится полный AspectJ, так как Spring AOP не осуществляет перехват доступа к полю (из-за того, как он реализован).

Идея состоит в том, что вы используете @Around, чтобы определить pointcut и получить такой совет:

static final OtherThing THE_DEFAULT_VALUE = ...;

@Around("execution(* getOtherThing())")
public Object supplyDefault(ProceedingJoinPoint pjp) throws Throwable {
    Object result = pjp.proceed();
    if (result == null)
        result = THE_DEFAULT_VALUE;
    return result;
}

Или, с AspectJ (не проверено; на самом деле я ни для чего не использовал AspectJ):

aspect ADefaultOtherThing {
    static final OtherThing THE_DEFAULT_VALUE = ...;

    OtherThing around(): get(OtherThing getOtherThing) {
        OtherThing result = proceed();
        if (result == null)
            result = THE_DEFAULT_VALUE;
        return result;
    }
}

Тем не менее, я бы задал вопрос, является ли это особенно хорошим использованием АОП. Наверняка было бы лучше поместить такую ​​бизнес-логику прямо в код? Гарантия того, что поле никогда не будет null, может показаться хорошим инвариантом.

2 голосов
/ 09 февраля 2012

Uff .. Это может быть больно, но я искренне рекомендую вам пройти через ваш код и поставить проверки на ноль везде, где это целесообразно, собрать для себя служебный класс, чтобы вы могли сделать что-то вроде

MyUtilityHelper.checkNotNull (toCheck, elegantMessage)

И заставьте этот метод генерировать что-то, о чем вы можете получить больше информации.

AOP здесь на самом деле не применим ИМХО, вы не хотите делать что-то с AOP, которое должно выполняться с последовательной логикой, просто потому, что код лучше для последовательной обработки ... AOP подходит, когда вы хотите добавить горизонтальный уровень функциональности, такой как безопасность, ведение журнала ...

...