Я пытаюсь написать сквозную аннотацию функциональности, чтобы добавить значения в 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.