只有一个接口
Foo
,有两个默认方法m1
、m2
。
有 3 个类
Foo1
、Foo2
、Foo3
实现 Foo
。 Foo3
不会覆盖方法 m1
,但 Foo1
、Foo2
会覆盖方法。
我想创建一个针对
Foo3
的 m1
方法的方面。
我尝试了
@Pointcut("bean(foo3) && execution(* *.m1(..))
,并且在Spring Boot运行时它可以正常工作。但是当我以编程方式创建代理对象进行单元测试时,它不起作用。
我知道
bean(foo3)
使它可以在Spring Boot下工作,但是我找不到任何替代方法来表达切入点,它在测试中仍然有效。在这种情况下我怎样才能让它发挥作用?
public interface Foo {
default Object m1() {
// doSomething
return Something;
}
default Object m2() {
// doSomething
return Something;
}
}
public class Foo3 implements Foo {
// not overriding any method.
}
@Component @Aspect
public class ExampleAspect {
@Pointcut("bean(foo3) && execution(* *.m1(..))")
public void exampleAspect() {}
@Around("exampleAspect()")
public Object proxyMethod(ProceedingJoinPoint joinPoint) throws Throwable {
// ...
Object result = joinPoint.proceed();
// ...
}
}
public Foo3Test {
Foo instance = new Foo3();
AspectJProxyFactory factory = new AspectJProxyFactory(instance);
factory.addAspect(new ExampleAspect());
Foo proxy = factory.getProxy();
proxy.m1(); // it didn't use proxy. invoke real method.
}
我尝试了这些切入点:
target(Foo3) && execution(* Foo.m1(..))
即使在Spring Boot下也无法工作within(Foo3) && execution(* Foo.m1(..))
即使在Spring Boot下也无法工作execution(Foo.m1(..))
有效,但所有 m1
方法都被代理我不是 Spring 专家,但为了使特殊的 Spring AOP 切入点指示符
bean
工作,我想您在测试中可能需要一个应用程序上下文。然而,我理解无需所有仪式即可创建快速运行的测试的必要性。幸运的是,这并不难实现。只需将切入点更改为:
@Pointcut("target(Foo3) && execution(* m1(..))")
public void exampleAspect() {}
我试过了,效果很好。这是我测试的方法:
package de.scrum_master.spring.q76824399;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class ExampleAspect {
@Pointcut("target(Foo3) && execution(* m1(..))")
public void exampleAspect() {}
@Around("exampleAspect()")
public Object proxyMethod(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println(joinPoint + " -> " + joinPoint.getTarget());
return joinPoint.proceed();
}
}
package de.scrum_master.spring.q76824399;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
public class Foo3Test {
public static void main(String[] args) {
ExampleAspect aspect = new ExampleAspect();
Foo[] instances = { new Foo1(), new Foo2(), new Foo3() };
for (Foo instance : instances) {
AspectJProxyFactory factory = new AspectJProxyFactory(instance);
factory.addAspect(aspect);
Foo proxy = factory.getProxy();
proxy.m1();
}
}
}
这是控制台日志:
10:45:11.823 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public java.lang.Object de.scrum_master.spring.q76824399.ExampleAspect.proxyMethod(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable
10:45:12.055 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public java.lang.Object de.scrum_master.spring.q76824399.ExampleAspect.proxyMethod(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable
10:45:12.071 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public java.lang.Object de.scrum_master.spring.q76824399.ExampleAspect.proxyMethod(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable
execution(Object de.scrum_master.spring.q76824399.Foo.m1()) -> de.scrum_master.spring.q76824399.Foo3@6eda5c9
请注意该方面如何找到
Foo1
、Foo2
、Foo3
的所有 3 个实例,但仅针对 Foo3
实例触发建议。