У меня есть метод, в котором есть реактивный код (RxJava).
У меня есть Aspect @around, обернутый вокруг него.
Настройка в порядке, она распечатывает следующим образом.
Но это происходит еще до того, как метод подписывается.
Есть ли способ настроить его таким образом, чтобы Aspect запускался только после того, как метод подписывается?
Мой класс Аспекта
@Aspect
public class AspectClass {
@Around("@annotation(someLogger) && execution(* *(..))")
public Object getMockedData(ProceedingJoinPoint pjp, SomeLogger someLogger) throws Throwable {
System.out.println("from aspect start: " + Thread.currentThread().getName());
Object actualResponse = pjp.proceed(methodArguments);
System.out.println("from aspect close: " + Thread.currentThread().getName());
return actualResponse;
}
}
Пользовательская аннотация
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeLogger {
String name() default "";
}
Метод, который аннотируется для использования аспекта.
@SomeLogger(name = "name")
public Single<Response> add(Request request) {
return sample(request)
.flatMapObservable(resultSet -> Observable.from(resultSet.getRows()))
.map(row -> Response.builder()
.sampleTimestamp(localDateTime(row.getInstant("sample")))
.build()
)
.first()
.toSingle()
.doOnSubscribe(() -> System.out.println("method is subbed: add " + Thread.currentThread().getName()))
.doOnEach(n -> System.out.println("method ends and doOnEach: add " + Thread.currentThread().getName()));
}
Как уже упоминалось, строки печати в классе аспектов печатаются еще до подписки, что неверно.
Таким образом, это текущий неправильный порядок печати.
from aspect start: eventloop-thread-3
from aspect close: eventloop-thread-3
method is subbed: add eventloop-thread-3
method ends and doOnEach: add eventloop-thread-3
Я ожидал следующего приказа.
method is subbed: add eventloop-thread-3
from aspect start: eventloop-thread-3
method ends and doOnEach: add eventloop-thread-3
from aspect close: eventloop-thread-3
Это возможно?
Это самый близкий вопрос, который я нашел по этому поводу. Написание аспектов для реактивных конвейеров
Но этот вопрос основан на Spring. Также в этом ответе есть строка:
Вы должны сообщить аспекту об асинхронной ситуации.
Похоже, это то, что мне нужно сделать, но как я могу это сделать? Спасибо за любой совет.
--- ОБНОВЛЕНИЕ после предложения ---
Отметим, что я использую AspectJ, а не Spring.
Это не работает, потому что перед подпиской переменная continue имеет значение null.
Таким образом, я добавил нулевую проверку. Но мы собираемся войти сюда только один раз.
Таким образом, continue.doOnSubscribe() никогда не происходит.
@Before("@annotation(someLogger) && execution(* *(..))")
public void before(JoinPoint jp, SomeLogger someLogger) throws Throwable {
Object[] args = jp.getArgs();
Single<?> proceed = ((Single<?>) ((ProceedingJoinPoint) jp).proceed(args));
if(proceed != null) {
proceed.doOnSubscribe(() -> System.out.println("doOnSubscribe in before"));
}
// this will print before a subscription
// as expected before which is not what I want.
System.out.println("inside before");
}
Дальнейшая попытка:
По крайней мере, теоретически ожидал, что это сработает. Но выдает ошибки компилятора AJC.
@Around("@annotation(someLogger) && execution(* *(..))")
public Object around(ProceedingJoinPoint pjp, SomeLogger someLogger) {
// return pjp.proceed(methodArguments); // compiles fine if no operations on method
return pjp.proceed(methodArguments)
.doOnSubscribe(() -> System.out.println("method is subbed: add " + Thread.currentThread().getName()))
.doOnEach(n -> System.out.println("method ends and doOnEach: add " + Thread.currentThread().getName()));
}
@Around
. Здесь подходятProceedingJoinPoint jp
иjp.proceed()
. Второй аспект после вашего редактирования показывает совет@Before
. Там вы должны использовать обычныйJoinPoint
, и вы никогда не вызываетеproceed()
, потому что, если вы не создадите исключение в совете, целевой метод будет выполнен автоматически после этого. Ваша попытка бросить и продолжить показывает, что вы этого не понимаете. Вы действительно должны прочитать некоторую документацию, а не просто взломать методом проб и ошибок. - person kriegaex   schedule 08.10.2020proceed()
еще более безумно. Я на 100% уверен, что вы никогда не найдете этого ни в одной документации, учебнике или примере кода. Это просто неправильно. Прежде чем беспокоиться оdoOnsubscribe()
, узнайте, как использовать AspectJ. Это было моей точкой зрения. - person kriegaex   schedule 08.10.2020@AfterReturning
, а не@Before
. Вы хотите сделать что-то после возврата метода, а не до. Если вы хотите изменить возвращаемое значение и/или сделать что-то до + после исходного метода, используйте@Around
. Вы не можете читать какую-либо документацию, если не знаете этого. Я действительно пытаюсь помочь здесь. В третий и последний раз ваша проблема не имеет ничего общего сdoOnSubscribe()
. Вам нужно практиковаться и понимать АОП. - person kriegaex   schedule 08.10.2020doOn*()
обратных вызовов в свой аспект к уже существующим в коде приложения? Я думал, ты хочешь перехватить существующие. Для меня это не имеет никакого смысла, и я также не сказал, что вы можете попробовать вместо этого в моем ответе, раздел B. - person kriegaex   schedule 14.10.2020