跨多个线程的春季方面

时间:2020-04-23 08:05:57

标签: java spring multithreading aop

尝试从两个方面包装服务类以获得此调用链:

javanica..HystrixCommandAspect-> MyCustomAroundAspect-> MyService

遇到两个问题:

  1. HystrixCommandAspect不调用joinPoint.proceed()。相反,它直接在目标类上调用方法,从而有效地跳过了javanica方面之后创建的其他任何代理

  2. Hystrix方面使后续调用在不同的线程中运行。它导致消息:

    “未找到MethodInvocation:检查AOP调用正在进行中,并且ExposeInvocationInterceptor在拦截器中位于前面...”

这是合理的,因为此拦截器将其内容保留在本地线程中。

问题: 1.为什么Spring APO是这样实现的?在不同线程中运行不同方面在概念上是否错误?除了更改方面的顺序之外,还有其他解决方法吗?

  1. 为什么HystrixCommandAspect直接调用目标类而不通过joinPoint.proceed()调用?它是否违反合同(如果甚至存在)?

致谢

1 个答案:

答案 0 :(得分:0)

免责声明:我不是Spring或Hystrix用户,而是AOP专家。

为什么HystrixCommandAspect直接调用目标类而不通过joinPoint.proceed()调用目标类?它是否违反合同(如果甚至存在)?

实际上,您必须询问Hystrix维护人员。实际上,这是一个好问题。 Hystrix方面是该宇宙中唯一方面的假设无疑是一个大胆的假设,因为实际上有@Around建议的AspectJ或Spring AOP合同:

  • 这两个方面都调用原始方法。如果这样做,则应使用proceed()。如果继续使用原始方法参数或修改后的参数集,则取决于方面。同样,如果它在执行其他操作之前,之后或之间进行。
  • 或者该方面返回的结果(对于非void方法)未经计算就返回原始方法。
  • 或者方面抛出异常,不返回任何结果。

话虽如此,我认为Hystrix中的一个设计缺陷是不传递ProceedingJoinPoint并最终对其调用proceed(),以防最终调用原始方法。如果我是Hystrix用户,那么我将为此打开一个故障单。

此外,从另一个线程中异步调用proceed()原则上是没有问题的,在创建创建时注入另一个连接点实例的线程。然后,您可以将该线程(或可运行线程)放入队列,并在方便时执行它。从技术上讲,您甚至可以在同一个连接点实例上多次调用proceed(),但是如果目标方法不是没有副作用的纯函数,则您可能需要注意这一点,除非您的方面实现了某些目标,否则通常不会这样做一种重试方案(有或没有指数补偿)。因此Hystrix也可以做到这一点。如果不这样做,那么他们必须做一些丑陋的事情,例如使用反射调用原始方法。我没有检查。