当前位置: 首页 > 知识库问答 >
问题:

Spring AOP代理和接口实现

傅高逸
2023-03-14

我试图理解Spring代理机制,但有一点我有问题。我有接口:

public interface MyInterface{
  void myMethod();
}

和实现类:

@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");
    }
}

我有简单的入门课程:

@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文档,我们可以阅读:

如果要代理的目标对象实现了至少一个接口,那么将使用JDK动态代理。目标类型实现的所有接口都将被代理。如果目标对象未实现任何接口,则将创建CGLIB代理。

但是我得到一个错误,没有定义[MyBean]类型的限定bean。仅当我通过@enableAspectProxy(proxyTargetClass=true)启用CGLib代理时,它才起作用。有人能解释一下我遗漏了什么吗?为什么在使用AOP时没有发现MyBean<代码>ctx。getBean(MyInterface.class)可以工作,但我无法想象这种接口的许多实现的情况。

共有2个答案

况景龙
2023-03-14

因为如果您检查您的bean类,您会发现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
}
邹祺然
2023-03-14

要代理的目标对象(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);

作品。

...但是我无法想象这种接口的许多实现的情况。

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

 类似资料:
  • 接口封装和代码整理 使用 OpenSBI 提供的服务 OpenSBI 实际上不仅起到了 bootloader 的作用,还为我们提供了一些底层系统服务供我们在编写内核时使用,以简化内核实现并提高内核跨硬件细节的能力。这层底层系统服务接口称为 SBI(Supervisor Binary Interface),是 S Mode 的 OS 和 M Mode 执行环境之间的标准接口约定。 参考 OpenSB

  • 他能给我建议和解决方案。非常感谢。请帮帮我!

  • 本文向大家介绍实现Runnable接口和Callable接口的区别?相关面试题,主要包含被问及实现Runnable接口和Callable接口的区别?时的应答技巧和注意事项,需要的朋友参考一下 如果想让线程池执行任务的话需要实现的Runnable接口或Callable接口。 Runnable接口或Callable接口实现类都可以被ThreadPoolExecutor或ScheduledThreadP

  • 代理商接口用于合作商直接调用来创建和管理果盘平台账号。 此部分接口需要用代理商接口msid和apikey来发起调用,不能用商家账号和密钥来调用。 代理商msid和apikey如下图,需要登录代理商后台->开发管理->APP应用管理中获取。

  • 代理商接口用于合作商直接调用来创建和管理果盘平台账号。 此部分接口需要用代理商接口msid和apikey来发起调用,不能用商家账号和密钥来调用。 代理商msid和apikey如下图,需要登录代理商后台->开发管理->APP应用管理中获取。

  • 我试图实现Comparable和compareTo(),但似乎无法实现。我一直在尝试不同的方法,但我真的不明白。我知道我应该实现可比较的接口,并且我需要在使用它之前创建方法(对我来说很奇怪,从python到面向对象编程)。 我希望它能比较两个人的年龄,所以我试着编写如下所示的代码,但似乎我不能使用compareTo()。我收到错误消息:“此方法必须返回int类型”,但在我看来,我只返回1、-1和0

  • 首先重构代码,让事件监听和事件处理分离开,各自责任更加独立。否则想将Echo功能替换为返回静态文件,又需要到处改代码。将责任分开后,只需要传入不同的事件处理器,即可实现不同效果。 增加EventHandler接口专门进行事件处理,SocketEventListener类中事件处理抽取到专门的EchoEventHandler实现中。 提前出AbstractEventListener类,规定了事件处理