我有一个Aspect拦截用注释@Foo修饰的方法a()。这种方法 调用另一个方法b()也用注释@Foo修饰。我希望我的方面能够拦截 只有a()而不是b()。我怎样才能做到这一点?
我已尝试过()但没有成功。使用ThreadLocal它可以工作,但我很想知道 如果有一个Spring解决方案。
@Component
@Order(value = 2)
@Aspect
public class FooAspect {
@Around(value = "@annotation(Foo)")
public Object aroundAdvice(ProceedingJoinPoint pjp, Foo foo) {
...
}
}
答案 0 :(得分:2)
我认为只有Aspects才能做到这一点。无论如何都会发生拦截。
但是,一种解决方案是使用ThreadLocal
Byte
标记您已经应用了建议。
private ThreadLocal<Byte> flag = new ThreadLocal<>();
@Around(value = "@annotation(Foo)")
public Object aroundAdvice(ProceedingJoinPoint pjp, Foo foo) throws Throwable {
if (flag.get() == null) {
try {
flag.set((byte) 1); // or 0, whatever
// apply advice
return pjp.proceed();
} finally {
flag.remove();
}
} else {
// don't apply advice
return pjp.proceed();
}
}
您需要catch
或throws
Throwable
引发proceed()
。
答案 1 :(得分:0)
框架中有cflow
个poincut
,但Aspectj风格不支持它。
但是,您可以将其与aop-schema配置方法一起使用。
例如:
public class NotInFlowPoincut extends AspectJExpressionPointcut {
private ControlFlowPointcut cflow;
private Class<?> flowClass;
private String methodName;
public NotInFlowPoincut() {
}
@PostConstruct
public void init() {
cflow = new ControlFlowPointcut(flowClass, methodName);
}
@Override
public boolean matches(Method method, Class targetClass, Object[] args) {
return super.matches(method, targetClass, args) && ! cflow.matches(method, targetClass, args);
}
public Class<?> getFlowClass() {
return flowClass;
}
public void setFlowClass(Class<?> flowClass) {
this.flowClass = flowClass;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
}
public class FooAspect {
public Object aroundAdvice(ProceedingJoinPoint pjp, Foo foo) throws Throwable {
System.out.println("in aroundAdvice");
return pjp.proceed();
}
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/context.xml");
A a = ctx.getBean(A.class);
a.a();
B b = ctx.getBean(B.class);
b.b();
}
}
public class A {
@Autowired B b;
@Foo
public void a() {
System.out.println("In a()");
b.b();
}
}
public class B {
@Foo
public void b() {
System.out.println("In b()");
}
}
最后
<bean id="cflow" class="test.NotInFlowPoincut">
<property name="expression" value="@annotation(foo) " />
<property name="methodName" value="aroundAdvice" />
<property name="flowClass" value="test.FooAspect" />
</bean>
<bean id="foo" class="test.FooAspect" />
<bean id="a" class="test.A" />
<bean id="b" class="test.B" />
<aop:config proxy-target-class="true">
<aop:aspect ref="foo" >
<aop:around method="aroundAdvice" pointcut-ref="cflow" />
</aop:aspect>
</aop:config>
将输出:
in aroundAdvice
In a()
In b()
in aroundAdvice
In b()
这似乎就是你要找的东西。
请注意,cflow poincut很慢,请参阅javadoc。