Аспекты Spring в нескольких потоках - PullRequest
0 голосов
/ 23 апреля 2020

Попытка обернуть класс обслуживания двумя аспектами для получения этой цепочки вызовов:

javanica..HystrixCommandAspect -> MyCustomAroundAspect -> MyService

встретились две проблемы:

  1. HystrixCommandAspect не звонит joinPoint.proceed(). Вместо этого он вызывает метод непосредственно для целевого класса, который эффективно пропускает любые другие прокси, созданные после аспекта javanica

  2. Аспект Hystrix делает последующие вызовы выполняющимися в другом потоке. Это приводит к сообщению:

    «Метод MethodInvocation не найден: убедитесь, что выполняется вызов AOP и что ExposeInvocationInterceptor находится в перехватчике в прямом направлении ...»

, что разумно, потому что этот перехватчик сохраняет свои данные в локальном потоке.

Вопросы: 1. Почему Spring APO реализован таким образом? Концептуально неправильно запускать разные аспекты в разных потоках? Есть ли обходные пути, кроме изменения порядка аспектов?

Почему HystrixCommandAspect вызывает целевой класс напрямую, а не через joinPoint.proceed()? Разве это не нарушает контракт (если он вообще существует)?

regards

1 Ответ

0 голосов
/ 24 апреля 2020

Отказ от ответственности: я не являюсь пользователем Spring или Hystrix, а просто парнем из AOP.

Почему HystrixCommandAspect вызывает целевой класс напрямую, но не через joinPoint.proceed() ? Разве это не нарушает контракт (если он вообще существует)?

На самом деле, вы должны спросить сопровождающего Hystrix. На самом деле это хороший вопрос. предположение о том, что аспекты Hystrix являются единственными в этой вселенной, безусловно, смелое, потому что на самом деле существует контракт AspectJ или Spring AOP для @Around совета:

  • Либо аспект вызывает оригинальный метод. Если это так, он должен использовать proceed(). Если это продолжается с исходными аргументами метода или с измененным набором, это до аспекта. Также, если это происходит до, после или между выполнением других действий.
  • Или аспект возвращает результат (для не пустых методов), вычисленный без перехода к исходному методу.
  • Или аспект выдает исключение, не возвращая никакого результата.

Сказав это, я думаю, что в Hystrix есть недостаток, заключающийся в том, чтобы не передавать ProceedingJoinPoint и в конечном итоге вызвать proceed() в случае, если оригинальный метод должен быть вызван в конце концов. Если бы я был пользователем Hystrix, я бы открыл для этого билет с ошибкой.

Кроме того, в принципе нет проблем вызвать proceed() асинхронно из другого потока, в который вы добавляете экземпляр точки соединения при создании. Затем вы можете поместить этот поток (или исполняемый файл) в очередь и выполнить его в любое удобное время. Технически, вы даже можете вызывать proceed() на одном и том же экземпляре точки соединения несколько раз, но если целевой метод не является чистой функцией без побочных эффектов, вы можете быть осторожны с этим и обычно не сделаете этого, если ваш аспект не реализует какой-то вид схема повтора (с экспоненциальным отступом или без него). Так что Hystrix мог и к этому. Если они этого не делают, то вместо этого они должны делать что-то безобразное, например, использовать рефлексию для вызова оригинального метода. Я не проверял.

...