AspectJ Interceptor无法正常工作

时间:2017-03-13 11:25:14

标签: java aop aspectj spring-aop interceptor

我创建了一个像

这样的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){}

但它仍然不起作用。

2 个答案:

答案 0 :(得分: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。谢谢。

答案 1 :(得分:0)

对我而言看起来不错,但我不确定你是否错过了@Aspect。另一种方法是在单一位置组合切入点和建议。为了避免包名中的任何错误,我将e.f.g.findPluginForRequest替换为findPluginForRequest。一旦确定包名

没有任何问题,你可以把它放回去
@Aspect
public class LoggingAspect {

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

    }

}