Я работаю над реактивным проектом Spring Web, и в настоящее время я внедряю набор различных метрик для запросов.Оказывается, наличие нескольких аннотаций @Around, взаимодействующих с объектом возврата Mono моего метода rest-controller, заставляет Spring генерировать исключение IllegalStateException.
Я использую Java 11 с пружинной загрузкой 2.1.5-RELEASE
Я прошел по пружинному коду и попытался выяснить, что именно происходит не так, и мне кажется, что при вызове продолжения () в ProceedingJoinPoint логика spring aop смешивает аргументы разных аннотаций.В частности, вызов getUserAttribute в строке AbstractApsectJAdvice 684 возвращает значение NULL и, по-видимому, имеет неверный аргумент.Я также попытался изменить порядок методов аспектов безуспешно.
Следующий метод - это рассматриваемый обработчик остатка, аннотации @TimedMono и @HostLanguageRequestCounting оба добавляют в цепочку реактора
@Counted("statistics_incoming_requests")
@TimedMono("statistics_incoming_requestExecutionTime")
@PostMapping("/translate/{id}/{field}")
@HostLanguageRequestCounted("statistics_incoming_hostLanguageRequestCount")
public Mono<TranslationResponseBody> getTranslation(@PathVariable String id,
@PathVariable String field,
@RequestBody TranslationRequestBody requestBody) {
return translateService.translate(id, requestBody.getTargetLanguage(), requestBody.getText(), field);
}
Это метод обработки аннотации TimedMono:
@Around(value = "@annotation(timed)")
@Order(2)
@SuppressWarnings("checkstyle:illegalThrows")
public Mono<?> timeExecution(ProceedingJoinPoint pjp, TimedMono timed) throws Throwable {
Long tStart = System.nanoTime();
Object m = pjp.proceed();
long tEnd = System.nanoTime();
if (!(m instanceof Mono)) {
throw (new Exception("Method must return a mono object"));
}
Mono<?> mono = (Mono) m;
Consumer<Object> stopTimer = obj -> {
meterRegistry.timer(timed.value())
.record(tEnd - tStart, TimeUnit.NANOSECONDS);
};
return mono.doOnError(stopTimer).doOnNext(stopTimer);
}
И метод обработки аннотации HostLanguageRequestCounting:
@Around(value = "@annotation(hostLanguageRequestCounted)")
@Order(1)
public Object gatherTenantMetrics(ProceedingJoinPoint pjp,
HostLanguageRequestCounted hostLanguageRequestCounted) throws Throwable {
Optional<TranslationRequestBody> body = HostLanguageRequestCountedMetricAspect
.getArgumentOfType(TranslationRequestBody.class, pjp);
return Mono.subscriberContext()
.flatMap(ctx -> {
log.info(ctx.toString());
return Mono.just(ctx.get("host"));
}).flatMap(host -> {
if (host != null && body.isPresent() && body.get().getTargetLanguage() != null) {
String metricKey = hostLanguageRequestCounted.value();
metricKey += "_" + host.toString().toLowerCase();
metricKey += "_" + body.get().getTargetLanguage().toLowerCase();
meterRegistry.counter(metricKey).increment();
}
try {
return (Mono<?>) pjp.proceed();
} catch (Throwable t) {
return Mono.error(t);
}
});
}
private static <T> Optional<T> getArgumentOfType(Class<T> clazz, ProceedingJoinPoint pjp) {
return Arrays.stream(pjp.getArgs())
.filter((arg) -> clazz.isAssignableFrom(arg.getClass()))
.map((obj) -> (T) obj).findFirst();
}
, в котором генерируется исключение (при возврате (Mono) pjp.continue ();)
Выдается следующее исключение:
java.lang.IllegalStateException: требуется для связывания 2 аргументов, но только для 1 (JoinPointMatch НЕ было связано в вызове) в org.springframework.aop.aspectj.AbstractAspectJAdvice.argBinding (AbstractAspectJAdvice.java:605) в org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod (AbstractAspectJAdvice.jworkj.fa..a.asa.pris.aa.вызвать (AspectJAroundAdvice.java:70) в org.springframework.aop.frameРаботав моем коде.
Это настоящая ошибка весной или я что-то не так делаю?Когда я удаляю одну из аннотаций, другая выполняется без проблем.