I was reading some articles about Spring AOP and encountered this:
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.
Could you look at the following structure and imagine that we want to advise bar()
method.
public interface Foo {
void foo();
}
public class FooImpl implements Foo {
@Override
public void foo() {
System.out.println("");
}
public void bar() {
System.out.println("");
}
}
Does it mean that in this case CGLIB proxy will be used?
Since JDK dynamic proxy isn't able to implement any interface in order to override bar()
method.
Spring will only use CGLIB if you tell it to. This is enabled (for annotation based configurations) by setting the proxyTargetClass
element of @EnableAspectJAutoProxy
to true
.
@EnableAspectJAutoProxy(proxyTargetClass = true)
Consider this minimal example (assuming your FooImpl
is annotated with @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();
}
}
By default, proxyTargetClass
is false
. In this case, Spring will not use CGLIB. Because of the @Before
advice in the @Aspect
class, Spring will decide that it needs to proxy the FooImpl
with a JDK proxy. Unfortunately, because of this proxying behavior, the bean actually stored in the context will be of a dynamic JDK Proxy
type (also a subtype of the Foo
interface) and therefore trying to get the bean with FooImpl.class
will fail.
Even if you tried to retrieve it as a Foo
, you wouldn't be able to invoke a bar()
method since the proxy object isn't a FooImpl
.
If you enable the proxyTargetClass
, the code above works as intended, a CGLIB proxy is created, and the @Before
advice is invoked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With