Java SpringAOP何时使用CGLIB代理?

Java SpringAOP何时使用CGLIB代理?,java,spring,proxy,spring-aop,cglib,Java,Spring,Proxy,Spring Aop,Cglib,我在读一些关于Spring AOP的文章时遇到了以下问题: AOP代理:AOP创建的用于实现方面的对象 合同。在Spring中,代理对象可以是JDK动态代理或 CGLIB代理。默认情况下,代理对象将是JDK动态的 代理,并且被代理的对象必须实现一个接口, 这也将由代理对象实现。但是像这样的图书馆 CGLIB也可以通过子类化来创建代理,因此 接口是不需要的 您能看看下面的结构并想象一下我们想要建议bar()方法吗 public interface Foo { void foo(); }

我在读一些关于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 dynamic proxy无法实现任何接口来重写
bar()
方法。

Spring只会在您要求的情况下使用CGLIB。通过将
@enableSpectJautoProxy
proxyTargetClass
元素设置为
true
,可以启用此功能(对于基于注释的配置)

public interface Foo {
    void foo();
}

public class FooImpl implements Foo {

    @Override
    public void foo() {
        System.out.println("");
    }

    public void bar() {
        System.out.println("");
    }

}
@EnableAspectJAutoProxy(proxyTargetClass = true)
考虑这个最小的例子(假设您的
FooImpl
是用
@组件注释的

默认情况下,
proxyTargetClass
false
。在这种情况下,Spring将不使用CGLIB。由于
@Aspect
类中的
@Before
建议,Spring将决定需要使用JDK代理代理
FooImpl
。不幸的是,由于这种代理行为,实际存储在上下文中的bean将是动态JDK
Proxy
类型(也是
Foo
接口的子类型),因此尝试使用
FooImpl.class
获取bean将失败

即使尝试将其作为
Foo
检索,也无法调用
bar()
方法,因为代理对象不是
FooImpl


如果启用
proxyTargetClass
,上述代码将按预期工作,将创建CGLIB代理,并在调用
建议之前调用

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

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

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

请参见Spring文档中的:


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

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


这取决于--您是如何注入bean的?谢谢,但是您能解释一下为什么会在您的代码片段中抛出异常吗?如果我们无法检索/调用JDK dynamic proxy,那么使用JDK dynamic proxy建议该方法的目的是什么?@Pavel尽管
FooImpl
@component
注释,但由于该建议,它也是代理的目标。因此,Spring将为它创建一个代理类型的bean定义,因此不是
FooImpl