Spring AOP代理和接口实现

Spring AOP proxy and interface implementation

我正在尝试了解 Spring 代理机制,但我遇到了一件事。 我有接口:

public interface MyInterface{
  void myMethod();
}

并实施 class:

@Component
public class MyBean implements MyInterface{
  @Override
  public void myMethod(){
    //do something
  }
}

现在我创建Aspect,例如:

@Aspect
@Component
public class LogAspect {
    @Before("execution(public * *(..))")
    public void logBefore() {
        System.out.println("Before aspect");
    }
}

我有简单的启动器class:

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class SpringAopApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
                SpringAopApplication.class);

        MyBean bean = ctx.getBean(MyBean.class);
//      MyInterface bean = ctx.getBean(MyInterface.class); //works
        bean.myMethod();

        ctx.close();
    }
}

根据 Spring 文档,我们可以阅读:

If the target object to be proxied implements at least one interface then a JDK dynamic proxy will be used. All of the interfaces implemented by the target type will be proxied. If the target object does not implement any interfaces then a CGLIB proxy will be created.

但是我得到一个错误没有定义 [MyBean] 类型的合格 bean。只有当我通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 启用 CGLib 代理时它才有效。 有人可以解释我在这里缺少什么吗?为什么在使用 AOP 时没有发现 MyBean? ctx.getBean(MyInterface.class) 可以,但我无法想象这种接口有很多实现的情况。

被代理的目标对象(MyBean)至少实现了一个接口(MyInterface),所以使用了JDK代理。 此代理实现 MyInterface,但不是 MyBean 的实例。 这就是为什么

MyInterface bean = ctx.getBean(MyInterface.class);

有效并且

MyBean bean = ctx.getBean(MyBean.class);

没有。

CGLib 代理是通过子类化目标对象创建的,因此创建的 bean 是 MyBean 的子类并实现了 MyInterface。 在这种情况下也

MyBean bean = ctx.getBean(MyBean.class);

有效。

...but I can't imagine the situation with many implementations of such interface.

MyInterface 的唯一原因可能是允许 spring 创建一个 JDK 代理,因此不需要有很多实现。

因为如果您检查 bean class,您会发现 com.sun.proxy.$Proxy21(或类似的东西),它包装了您的方法。它们是不兼容的类型,即使它们具有相同的接口。 例如:

public interface AnInterface {
   void func();
}

public class Bb implements AnInterface{
   @Override
   public void func() {
      System.out.println("bb");
   }
}

public class Cc implements AnInterface{
@Override
   public void func() {
      System.out.println("cc");
   }
}

所以当你打电话给

public static void main(String[] args) {
    Bb b = new Bb();
    Cc c=b; // Error
    AnInterface c=b; // Ok
}