AspectJ 拦截器不工作

问题描述 投票:0回答:2

我创建了一个像

这样的 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<BSFBatchRequest, BSFReply> findPluginForRequest(final BSFBatchRequest request)
。我尝试将切入点更改为

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

但是还是不行。

java aop aspectj spring-aop interceptor
2个回答
1
投票

我可以回答你的问题:

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

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

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

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


0
投票

对我来说看起来不错,但我不确定你是否错过了

@Aspect
。另一种方法是,您可以在单个位置结合切入点和建议。为了避免包名称出现任何错误,我将
e.f.g.findPluginForRequest
替换为
findPluginForRequest
。确定包名没有问题就可以放回去了

@Aspect
public class LoggingAspect {

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

    }

}
© www.soinside.com 2019 - 2024. All rights reserved.