Будет ли аспект выполняться асинхронно, если я добавлю в него метод @Async? - PullRequest
1 голос
/ 07 октября 2019

У меня есть класс ControllerLogger, в котором есть несколько методов с аннотациями @Before и @AfterReturning.

Будут ли они выполняться асинхронно, если я добавлю @Async для каждого из них вместе с @EnableAsync?

Как тогда будут разрешены и созданы прокси для методов и будут ли они?

1 Ответ

4 голосов
/ 08 октября 2019

Что меня поразило, когда я прочитал твой вопрос: почему бы тебе не попробовать вместо того, чтобы задать вопрос здесь и ждать ответа? Через минуту вы узнаете.

Второй вопрос: зачем вам создавать новое задание каждый раз, когда выполняется совет аспекта? Это действительно будет быстрее, чем синхронное выполнение? Из твоего аспекта имя ControllerLogger я прихожу к выводу, что все это делает запись. Но в любом случае, возможно, ваша регистрация ведется так медленно, что имеет смысл сделать ее асинхронной. Обычно вы уже можете настроить это для своей среды ведения журналов, поэтому аспекту не нужно об этом заботиться.

Наконец, ответ на ваш вопрос: я никогда не пробовал это раньше, но мне потребовалось две минуты, чтобыtest:

  • Добавьте оператор типа System.out.println(Thread.currentThread() + " -> " + Thread.currentThread().getId()); как к совету по аспектам, так и к целевому методу.
  • Выполните без @Async / @EnableAsync. Обратите внимание на результаты.
  • Запустите снова с @Async / @EnableAsync. Обратите внимание на результаты.

Для меня я видел нечто подобное раньше:

Thread[main,5,main] -> 1
Thread[main,5,main] -> 1
Thread[main,5,main] -> 1
Thread[main,5,main] -> 1

И это после активации асинхронного выполнения (выполнено 3 аспектных совета):

Thread[main,5,main] -> 1
Thread[SimpleAsyncTaskExecutor-1,5,main] -> 18
Thread[SimpleAsyncTaskExecutor-2,5,main] -> 25
Thread[SimpleAsyncTaskExecutor-3,5,main] -> 26

Таким образом, ответ таков: Да, советы по аспектам, такие как @Before или @After для Spring AOP, будут выполняться асинхронно.

Будьте осторожны с советами @Around, хотя, потому что если целевые методыи, следовательно, также общий совет) возвращает тип, отличный от void или Future (как описано в Javadoc аннотации @Async), вы получите исключения времени выполнения, потому что асинхронно выполненный совет вернет null перехваченному методу первым. Таким образом, вы увидите исключение, подобное следующему:

Exception in thread "main" 
org.springframework.aop.AopInvocationException: Null return value from advice does not match primitive return type for: public int spring.aop.MyController.doSomething(java.lang.String,int)
    at org.springframework.aop.framework.CglibAopProxy.processReturnType(CglibAopProxy.java:362)
    at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:84)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:658)
    at spring.aop.MyController$$EnhancerBySpringCGLIB$$c28d13a5.doSomething(<generated>)
    at spring.aop.DemoApplication.main(DemoApplication.java:28)

Поэтому обязательно используйте @Async + @Around только в тех случаях, для которых асинхронное выполнение действительно имеет смысл и для которых была разработана аннотация.


Обновление: Вышеуказанное исключение будет отображаться только для методов, возвращающих примитивные типы, например, если ваш метод возвращает int и выполняется рекомендация обойти и вызывать JoinPoint.proceed(). Если тот же самый метод вернет Integer, вместо этого совет округления будет выполнен без ошибки, но вернет null, чего ваш вызывающий объект не ожидает и может привести к поломке вашей программы. Поэтому, как я уже сказал, будьте осторожны, как использовать это с @Around.


Обновление 2: Даже если целевой метод возвращает Future, но совет вокруг возвращает что-тодругие, например, Object, proceed() вернут null. Только если вы сделаете так, чтобы совет по округлению также имел тип возврата Future, он действительно работает, и вызывающая сторона может обработать будущее так, как ожидается, и после ожидания isDone() фактически получит ожидаемый результат.

...