我创建了一个像
这样的 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){}
但是还是不行。
我可以回答你的问题:
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。
对我来说看起来不错,但我不确定你是否错过了
@Aspect
。另一种方法是,您可以在单个位置结合切入点和建议。为了避免包名称出现任何错误,我将 e.f.g.findPluginForRequest
替换为 findPluginForRequest
。确定包名没有问题就可以放回去了
@Aspect
public class LoggingAspect {
@Before("execution(* findPluginForRequest(..))&& args(request)")
public void beforeeAdvice(BSFBatchRequest request ){
}
}