Java 如果我将@Async方法放在一个方面上,它会异步执行吗?

Java 如果我将@Async方法放在一个方面上,它会异步执行吗?,java,spring,asynchronous,aop,Java,Spring,Asynchronous,Aop,我有一个ControllerLogger类,它有一些方法,在返回注释之前,之后 如果我将@Async与@EnableAsync一起放在它们上面,它们会开始异步执行吗 那么,如何为这些方法解析和创建代理,它们会是什么呢?阅读您的问题时,我首先想到的是:为什么您不尝试一下,而不是在这里提问并等待答案?一分钟后你就会知道了 第二个问题是:为什么每次执行方面的建议时都要创建一个新任务?这真的会比同步执行快吗?从您的方面名称ControllerLogger我得出结论,它所做的一切都是日志记录。但无论如何,

我有一个
ControllerLogger
类,它有一些方法,在返回注释之前
,之后

如果我将
@Async
@EnableAsync
一起放在它们上面,它们会开始异步执行吗


那么,如何为这些方法解析和创建代理,它们会是什么呢?

阅读您的问题时,我首先想到的是:为什么您不尝试一下,而不是在这里提问并等待答案?一分钟后你就会知道了

第二个问题是:为什么每次执行方面的建议时都要创建一个新任务?这真的会比同步执行快吗?从您的方面名称
ControllerLogger
我得出结论,它所做的一切都是日志记录。但无论如何,可能您的日志记录速度太慢了,所以将其异步化实际上是有意义的。通常,您已经可以为日志框架配置它,因此方面不需要处理它

最后回答你的问题:我以前从未尝试过,但我花了两分钟来测试:

  • 添加类似于
    System.out.println(Thread.currentThread()+“->”+Thread.currentThread().getId())的语句
    同时添加到aspect建议和目标方法
  • 在没有
    @Async
    /
    @EnableAsync
    的情况下运行。注意结果
  • 使用
    @Async
    /
    @EnableAsync
    再次运行。注意结果
对我来说,我以前见过这样的事情:

Thread[main,5,main]>1
线程[main,5,main]->1
线程[main,5,main]->1
线程[main,5,main]->1
在激活异步执行后(执行3个方面):

Thread[main,5,main]>1
线程[SimpleAsyncTaskExecutor-1,5,main]->18
线程[SimpleAsyncTaskExecutor-2,5,主]->25
线程[SimpleAsyncTaskExecutor-3,5,主]->26
因此答案是:是的,Spring AOP的方面建议,如
@之前
@之后
将异步执行

但是要小心使用
@Around
通知,因为如果目标方法(以及Around通知)返回的类型不是
void
Future
(如中所述),您将获得运行时异常,因为异步执行的通知将首先向截获的方法返回
null
。所以你会看到这样一个例外:

线程“main”中出现异常 org.springframework.aop.aopinocationexception:advice的Null返回值与public int spring.aop.MyController.doSomething(java.lang.String,int)的基元返回类型不匹配 位于org.springframework.aop.framework.CglibAopProxy.processReturnType(CglibAopProxy.java:362) 位于org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:84) 位于org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:658) 在spring.aop.MyController$$EnhancerBySpringCGLIB$$c28d13a5.doSomething()中 位于spring.aop.DemoApplication.main(DemoApplication.java:28)
因此,请确保仅在异步执行确实有意义并且注释是为其设计的情况下使用
@Async
+
@Around


更新:上述异常只会在返回基元类型的方法中出现,例如,如果您的方法返回
int
并且执行了一个around通知并调用
JoinPoint.procedue()
。如果相同的方法返回
Integer
,则执行around通知时不会出错,但返回
null
,这是调用者不希望看到的,可能会破坏程序。正如我所说的,在使用
@时要小心



更新2:即使目标方法返回一个
未来
,但around通知返回其他内容,例如
对象
继续()
将返回
null
。只有当您发出的around通知的返回类型也为
Future
,它才能实际工作,并且调用方可以在等待
isDone()后按预期处理未来
实际收到了预期的结果。

显示您当前的代码并解释您想要更改的内容。请注意我关于
@周围
+
@Async
问题的更新。