Вы создали аннотацию @UserAnnotation
и класс-перехватчик для добавления аннотации.Вы присоединяете аннотацию к методу userMethod()
.
Первое, что делает ваша подпрограмма-перехватчик, - это вызывает userMethod()
, чтобы получить наблюдаемое, которое она возвращает, и затем перехватчик подписывается навозвращается наблюдаемым, в результате чего появляются первые сообщения журнала.В конце концов, перехватчик возвращает наблюдаемое исходному вызывающему.Когда что-то еще присоединяется к возвращаемой наблюдаемой, цепочка наблюдателей активируется второй раз, поэтому сообщения журнала появляются дважды.
RxJava имеет побочные эффекты
Пока RxJava являетсяреализация концепции «функционально-реактивного программирования», цепочки наблюдателей, которые вы строите (функционально), работают только тогда, когда на них подписаны, и эти подписки имеют побочные эффекты.Регистрация выходных данных является одним из побочных эффектов и, вероятно, наиболее благоприятным;изменения в переменных или вызовы методов, которые имеют побочные эффекты, оказывают более широкое влияние.
Когда построена цепочка наблюдателей (правильно), она действует как потенциальное вычисление, пока не будет подписчик.Если вам нужно иметь более одного подписчика, как, например, для проблемного домена, вам нужно решить, нужно ли активировать цепочку наблюдателей для каждой подписки, обычного случая или только один раз для всех перекрывающихся подписок.
Если вы хотите, чтобы у всех перекрывающихся подписок была одна и та же наблюдаемая, вы можете использовать оператор share()
.Существует ряд связанных операторов, которые влияют на время существования наблюдаемых и подписок.Вот краткий обзор: Как использовать оператор RxJava share ()?
Аспектно-ориентированное программирование: перехватчики и Guice
Ваш код использует Guiceпредоставить возможность под названием «аспектно-ориентированное программирование».Это позволяет вам вводить код в вашу программу для решения сквозных задач или для повышения ее функциональности путем настройки управляемых шлюзов.Использование Guice или аналогичных подходов AOP требует дисциплины .
. В вашем случае вы использовали процесс перехвата, чтобы вызвать необъяснимые (до сих пор) побочные эффекты, подписавшись на цепочку наблюдателей, у которой неттривиальные побочные эффекты.Представьте, что метод, который вы перехватили, установил одноразовое соединение, и ваш перехватчик использовал это соединение, выполняя свою работу, в результате чего исходный вызывающий абонент не смог использовать соединение.
Дисциплина, в которой вы нуждаетесь, заключается в понимании правилчто перехватчик должен следовать.Подумайте о таких правилах, как «Во-первых, не навреди».
Doing Things The FRP Way
Если вам нужно добавить дополнительный шаг при обработке информации пользователя, тогдавы должны создать новую наблюдаемую в вашем перехватчике, которая делает это, но только тогда, когда исходный вызывающий абонент подписался на наблюдаемую:
Object result = invocation.proceed();
Observable<List<User>> observable = (Observable<List<Sample>>) result;
Observable<List<User>> newObservable = observable
.doOnNext( sampleList ->
Observable.fromIterable( sampleList )
.subscribe(object -> {
User user = (User)object
SampleSender sender = new SampleSender();
sender.setBoolean(user.isBoolean());
logger.info("Pushing Data into Sender");
userService.insert(String.join("_", "key", "value"), sender);
}));
return newObservable;
Возвращая модифицированную цепочку наблюдателей, вы не вводите побочные эффекты от оригинала.цепочка наблюдателей и убедитесь, что побочные эффекты, которые вы вводите в свой собственный код, будут только запускаться при подписке на исходную цепочку наблюдателей.