我正在阅读一些关于 Spring AOP 的文章并遇到了这个问题:
AOP proxy: the object created by AOP to implement the aspect contracts. In Spring, proxy objects can be JDK dynamic proxies or CGLIB proxies. By default, the proxy objects will be JDK dynamic proxies, and the object being proxied must implement an interface, that will also be implemented by the proxy object. But a library like CGLIB can be used to create proxies by subclassing too, so an interface is not needed.
你能看看下面的结构并想象我们想要建议
bar()
方法。public interface Foo {
void foo();
}
public class FooImpl implements Foo {
@Override
public void foo() {
System.out.println("");
}
public void bar() {
System.out.println("");
}
}
这是否意味着在这种情况下将使用 CGLIB 代理?
由于 JDK 动态代理无法实现任何接口(interface)来覆盖
bar()
方法。
最佳答案
如果你告诉它,Spring 只会使用 CGLIB。这通过设置 proxyTargetClass
启用(对于基于注释的配置) @EnableAspectJAutoProxy
的元素至true
.
@EnableAspectJAutoProxy(proxyTargetClass = true)
考虑这个最小的例子(假设你的
FooImpl
用 @Component
注释)@Aspect
@Component
class FooAspect {
@Before("execution(public void bar())")
public void method() {
System.out.println("before");
}
}
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
FooImpl f = ctx.getBean(FooImpl.class); // throw exception here
f.bar();
}
}
默认情况下,
proxyTargetClass
是 false
.在这种情况下,Spring 不会使用 CGLIB。因为 @Before
@Aspect
中的建议类,Spring 将决定它需要代理 FooImpl
使用 JDK 代理。不幸的是,由于这种代理行为,实际存储在上下文中的 bean 将是动态 JDK Proxy
类型(也是 Foo
接口(interface)的子类型),因此尝试使用 FooImpl.class
获取 bean将失败。即使您尝试将其检索为
Foo
,您将无法调用 bar()
方法,因为代理对象不是 FooImpl
.如果启用
proxyTargetClass
,上面的代码按预期工作,创建了一个 CGLIB 代理,@Before
建议被调用。
关于java - Spring AOP 何时使用 CGLIB 代理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51795511/