【问题标题】:AspectJ Interceptor not workingAspectJ 拦截器不工作
【发布时间】:2017-03-13 11:25:13
【问题描述】:

我已经创建了一个像

这样的 AspectJ 拦截器
@Aspect
public class RequestSpecificServiceAspect {
    @Pointcut("execution( * com.mycompany.c.d.doesTreatmentEqualsAndTrigger(..))")
    private void callInterceptor(){}

    @Before("callInterceptor()")
    public void getCallStack(){
    StackTraceElement[] callingStack = Thread.currentThread().getStackTrace();
    PopulateServiceDependentMap populateServiceDependentMap = new PopulateServiceDependentMap();
    populateServiceDependentMap.populateMap(callingStack, "ServiceName");
    }
}

这工作得很好,因为这是一个试用代码,我现在用我想要的实际拦截器替换它,就像这样

@Pointcut("execution( * mycompany.f.g.findPluginForRequest(..)) && args(request)")
private void actualInterceptor(BSFBatchRequest request){}

@Before("actualInterceptor(request)")
public void getBSFCall(BSFBatchRequest request){ 
    StackTraceElement[] callingStack = Thread.currentThread().getStackTrace();
    PopulateServiceDependentMap populateServiceDependentMap = new PopulateServiceDependentMap();
    populateServiceDependentMap.populateMap(callingStack, request);
}

但现在我的拦截器没有拦截对findPluginForRequest() 函数的调用。 为什么会发生这种情况,我该如何解决?

这是我的 spring 配置文件(.xml):

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="no">
<context:annotation-config/>

<aop:aspectj-autoproxy/>

<bean name="com.dpx.dependencyGraphFactory" class="com.mycompany.dpx.dependencytree.ModuleToModuleDependencyGraphFactory"></bean>
<bean name="com.dpx.serviceInterceptor" class="com.mycompany.dpx.dependencytree.RequestSpecificServiceAspect"/>

</beans>

findPluginForRequest() 的签名是 private AllPurposeCache&lt;BSFBatchRequest, BSFReply&gt; findPluginForRequest(final BSFBatchRequest request)。我尝试将切入点更改为

@Pointcut("execution(private * mycompany.f.g.findPluginForRequest(..)) && args(request)")
private void actualInterceptor(BSFBatchRequest request){}

但还是不行。

【问题讨论】:

  • 我需要更多信息。请显示 findPluginForRequest 的包名称和签名,并告诉我是否在不删除 args() 部分和切入点/建议参数的情况下工作。另一个问题:在第一个示例中,您调用populateMap,第二个参数是一个字符串,现在它是一个请求对象。这是为什么呢?
  • 包名我不能告诉你保密协议的原因,但我可以告诉你它是一个普通的包。即使没有args() 部分,它也不起作用。为了回答第二个问题,我调用了一个请求对象,因为这个请求对象有一个方法可以返回一个字符串和一些我需要的更多数据。早些时候,因为这是一个试验,我只是硬编码该数据并传递字符串以检查它是否工作。
  • 您需要帮助,但不愿意分享足够的信息。我要了findPluginForRequest的签名。除非我至少看到了全貌的重要部分,否则这是一个让人们猜测的问答节目,而不是一个可以通过推理来回答的有意义的问题。
  • findPluginForRequest 的签名是 private AllPurposeCache&lt;BSFBatchRequest, BSFReply&gt; findPluginForRequest(final BSFBatchRequest request)。与此关系不大,但 AspectJ 拦截器会导致超时吗?

标签: java aop aspectj spring-aop interceptor


【解决方案1】:

既然你终于分享了方法签名,我可以回答你的问题了:

private AllPurposeCache<BSFBatchRequest, BSFReply> findPluginForRequest(
  final BSFBatchRequest request
)

Spring AOP 没有 AspectJ 强大,因为它不直接编织字节码,而是基于通过 JDK 或 CGLIB 创建/使用动态代理。动态代理只是实现接口的子类或类。因此,它们只覆盖公共方法。您的方法是私有的,因此 Spring AOP 无法拦截它。这记录在Spring AOP manual:

由于 Spring 的 AOP 框架基于代理的性质,根据定义,受保护的方法不会被拦截,对于 JDK 代理(如果不适用)和 CGLIB 代理(这在技术上可行但不推荐用于 AOP目的)。因此,任何给定的切入点都只会与公共方法匹配! 如果您的拦截需求包括受保护/私有方法甚至构造函数,请考虑使用 Spring 驱动的原生 AspectJ 编织,而不是 Spring 的基于代理的 AOP 框架。这就构成了不同特性的AOP使用模式不同,所以在做决定之前一定要先熟悉编织。

为了让它工作,要么公开方法,要么切换到 AspectJ。

P.S.:这本来可以更容易和更快。请了解how to ask a question on SO 以及如何提供minimal, complete, and verifiable example。谢谢。

【讨论】:

  • 我可以在 java 中直接使用 AspectJ 并在 xml 中进行一些更改吗?如果我能像 Spring AOP 一样使用 AspectJ,那就太好了。
  • 不想暴露一个方法是不是有点矫枉过正?我认为公开它是合理的,因为您想通过 AOP 与之交互。链接文档的第 11.8 章解释了如何配置 AspectJ。 RTFM,请。切换的决定不应该掉以轻心,尽管语法相同,但它确实是不同的。你好像对AOP知之甚少,小心别用大炮射蚊子。
  • 正如你所说。我是 AOP 新手,不太了解。问题还在于我试图拦截的方法由其他团队拥有,他们不允许将其公开。
  • 告诉他们代码不属于他们的团队,而是属于公司。如果你的工作是在他们的代码上实现一个横切关注点,他们应该改变它。或者,您需要找到另一个可以挂上钩的地方。让我们在这里停止讨论,这不再是技术性的了。
【解决方案2】:

对我来说看起来不错,但我不确定你是否错过了@Aspect。另一种方法是你可以在一个地方结合切入点和建议。为了避免包名出现任何错误,我将e.f.g.findPluginForRequest 替换为findPluginForRequest。确定包名没有问题后可以放回去

@Aspect
public class LoggingAspect {

    @Before("execution(* findPluginForRequest(..))&& args(request)")
    public void beforeeAdvice(BSFBatchRequest request ){

    }

}

【讨论】:

  • 这段代码在一个带有@Aspect注解的类中,所以没有问题。我会试着把它结合起来告诉你。
猜你喜欢
  • 2014-02-11
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
  • 2014-11-14
  • 2019-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多