代码之家  ›  专栏  ›  技术社区  ›  Pasha

Spring AOP何时使用CGLIB代理?

  •  0
  • Pasha  · 技术社区  · 8 年前

    我在读一些关于Spring AOP的文章时遇到了以下情况:

    AOP代理:AOP创建的用于实现方面的对象 合同。在Spring中,代理对象可以是JDK动态代理或 CGLIB代理。默认情况下,代理对象将是JDK动态的 代理,并且被代理的对象必须实现一个接口, 这也将由代理对象实现。但是像这样的图书馆 CGLIB也可以通过子类化来创建代理,因此 不需要接口。

    你能看看下面的结构,想象一下我们想要建议 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动态代理无法实现任何接口来覆盖 条形图() 方法

    2 回复  |  直到 5 年前
        1
  •  7
  •   Savior    8 年前

    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 接口),因此尝试使用 FooImpl.class 将失败。

    即使您试图将其作为 Foo公司 ,您将无法调用 bar() 方法,因为代理对象不是 FooImpl公司 .

    如果启用 proxyTargetClass ,上述代码按预期工作,创建CGLIB代理,然后 @之前 将调用通知。

        2
  •  3
  •   Community Mohan Dere    6 年前

    看见 AOP Proxies 在Spring文档中:

    Spring AOP默认使用标准JDK动态代理作为AOP代理。这允许代理任何接口(或一组接口)。

    Spring AOP还可以使用CGLIB代理。这对于代理类而不是接口是必要的。默认情况下,如果业务对象未实现接口,则使用CGLIB。

        3
  •  -2
  •   Pasha    8 年前

    Spring AOP默认使用标准JDK动态代理作为AOP代理。这允许代理任何接口(或一组接口)。

    Spring AOP还可以使用CGLIB代理。这对于代理类而不是接口是必要的。如果业务对象未实现接口,则默认情况下使用CGLIB。因为编程到接口而不是类是一种很好的做法;业务类通常将实现一个或多个业务接口。在需要建议未在接口上声明的方法的情况下,或者需要将代理对象作为具体类型传递给方法的情况下,可以强制使用CGLIB(希望很少)。

    掌握Spring AOP是基于代理的这一事实很重要。请参阅了解AOP代理,以全面了解此实现细节的实际含义。

    https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-introduction