Аннотация не работает при внутреннем вызове метода из другого метода в том же / другом классе - PullRequest
0 голосов
/ 12 апреля 2019

Я пытаюсь написать сквозную аннотацию функциональности, чтобы добавить значения в MDC перед выполнением метода. Однако я не могу сделать это, когда я вызываю метод из другого метода, и он дает NPE. Что мне делать?

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MDCAnnotated {
    MDCValue[] value() default {};
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface MDCValue {
    String key();
    String content() default "";
}
@Order(1)
@Service
@Aspect
public class MdcContextInitializer {

    private final String REQUEST_ID = "requestId";

    @Around("@annotation(com.example.test.annotation.MDCAnnotated)")
    public Object aroundAnnotatedMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MDCAnnotated annotation = method.getAnnotation(MDCAnnotated.class);
        setMdcContextForMethod(annotation);
        setMdcContextForMethodWithParameterDefinedValues(method.getParameters(), joinPoint.getArgs());
        return joinPoint.proceed();
    }

    private void setMdcContextForMethod(MDCAnnotated annotation) {
        boolean isRequestIdSpecificallyAdded = false;
        //Gives NPE in the following line
        for (MDCParam value : annotation.value()) {
            if (REQUEST_ID.equals(value.key())) {
                isRequestIdSpecificallyAdded = true;
            }
            MDC.put(value.key(), value.content());
        }
        if (!isRequestIdSpecificallyAdded) {
            MDC.put(REQUEST_ID, UUID.randomUUID().toString());
        }
    }

    private void setMdcContextForMethodWithParameterDefinedValues(Parameter[] parameters, Object[] args) {
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            MDCValue value = parameter.getAnnotation(MDCValue.class);
            if (value != null) {
                MDC.put(value.key(), String.valueOf(args[i]));
            }
        }
    }
}

Теперь, когда я пытаюсь использовать аннотацию, она работает для планировщика пружин здесь:

@Scheduled(cron = "${scheduling.example.cron}")
@ExtendMDC({
        @MDCValue(key = "Name 1", content = "Fixed Value 1"),
        @MDCValue(key = "Name 2", content = "Fixed Value 2")
})
public void test() {
    log.info(MDC.get("Name 1"));
    log.info(MDC.get("Name 2"));
    log.info(MDC.get("requestId"));
    myServiceFactory.getService(1).build();
    testService.test("rjw");
}

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

@Service
@Slf4j
public class TestServiceImpl implements TestService {

    @Override
    @ExtendMDC
    public void test(@MDCValue(key = "hj") String hj) {
        log.info("HJ:{}", MDC.get(hj));
    }
}

При обработке аспекта этого метода он дает NPE для аннотации в строке (закомментирован в классе аспектов для справки).

Как это возможно? Если бы не было аннотаций, они бы не попали только в Аспект. Разве это не так?

Как мне решить эту проблему?

P.S .: Я пометил свое SpringBootApplication @ EnableAspectJAutoProxy.

...