Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is CGLIB proxy used by Spring AOP?

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.

like image 719
Pasha Avatar asked Oct 20 '25 01:10

Pasha


1 Answers

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.

like image 50
Savior Avatar answered Oct 22 '25 05:10

Savior



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!