AspectJ 拦截器不工作
AspectJ Interceptor not working
我创建了一个像
这样的 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){}
但是还是不行。
我觉得不错,但我不确定你是否错过了 @Aspect
。另一种方法是将切入点和通知结合在一个地方。为了避免包名称中的任何错误,我将 e.f.g.findPluginForRequest
替换为 findPluginForRequest
。确定包名没有问题就可以放回去了
@Aspect
public class LoggingAspect {
@Before("execution(* findPluginForRequest(..))&& args(request)")
public void beforeeAdvice(BSFBatchRequest request ){
}
}
既然你终于分享了方法签名,我可以回答你的问题了:
private AllPurposeCache<BSFBatchRequest, BSFReply> findPluginForRequest(
final BSFBatchRequest request
)
Spring AOP 不如 AspectJ 强大,因为它不直接编织字节码,而是通过 JDK 或 CGLIB 基于 creating/using 动态代理。动态代理只是 sub类 或 类 实现接口。因此,它们只覆盖 public 方法。您的方法是私有的,因此 Spring AOP 无法拦截它。这记录在 Spring AOP manual:
Due to the proxy-based nature of Spring’s AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn’t applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only!
If your interception needs include protected/private methods or even constructors, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving first before making a decision.
为了使其正常工作,请创建方法 public 或切换到 AspectJ。
P.S.: 这本来可以更容易和更快。请学习how to ask a question on SO and how to provide a minimal, complete, and verifiable example。谢谢。
我创建了一个像
这样的 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){}
但是还是不行。
我觉得不错,但我不确定你是否错过了 @Aspect
。另一种方法是将切入点和通知结合在一个地方。为了避免包名称中的任何错误,我将 e.f.g.findPluginForRequest
替换为 findPluginForRequest
。确定包名没有问题就可以放回去了
@Aspect
public class LoggingAspect {
@Before("execution(* findPluginForRequest(..))&& args(request)")
public void beforeeAdvice(BSFBatchRequest request ){
}
}
既然你终于分享了方法签名,我可以回答你的问题了:
private AllPurposeCache<BSFBatchRequest, BSFReply> findPluginForRequest(
final BSFBatchRequest request
)
Spring AOP 不如 AspectJ 强大,因为它不直接编织字节码,而是通过 JDK 或 CGLIB 基于 creating/using 动态代理。动态代理只是 sub类 或 类 实现接口。因此,它们只覆盖 public 方法。您的方法是私有的,因此 Spring AOP 无法拦截它。这记录在 Spring AOP manual:
Due to the proxy-based nature of Spring’s AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn’t applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only! If your interception needs include protected/private methods or even constructors, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving first before making a decision.
为了使其正常工作,请创建方法 public 或切换到 AspectJ。
P.S.: 这本来可以更容易和更快。请学习how to ask a question on SO and how to provide a minimal, complete, and verifiable example。谢谢。