Spring:为什么我们自动连接接口而不是实现的类?

2022-08-31 06:55:26

interface IA
{
  public void someFunction();
}

@Resource(name="b")
class B implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someBfunc()
  {
     //doing b things
  }
}

@Resource(name="c")
class C implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someCfunc()
  {
     //doing C things
  }
}

class MyRunner
{

  @Autowire
  @Qualifier("b") 
  IA worker;

  worker.someFunction();
}

有人可以向我解释一下吗?

  • 弹簧如何知道要使用哪种多态类型。
  • 我需要还是?@Qualifier@Resource
  • 为什么我们自动连接接口而不是实现的类?

答案 1

弹簧如何知道要使用哪种多态类型。

只要接口只有一个实现,并且该实现在启用Spring的组件扫描的情况下进行注释,Spring框架就可以找出(接口,实现)对。如果未启用组件扫描,则必须在应用程序配置.xml(或等效的 spring 配置文件)中显式定义 Bean。@Component

我需要@Qualifier或@Resource吗?

一旦你有多个实现,那么你需要限定它们中的每一个,并且在自动连接期间,你需要使用注释来注入正确的实现,以及注释。如果使用@Resource(J2EE 语义),那么应该使用此注释的属性指定 Bean 名称。@Qualifier@Autowiredname

为什么我们自动连接接口而不是实现的类?

首先,一般来说,编码到接口始终是一种很好的做法。其次,在弹簧的情况下,您可以在运行时注入任何实现。一个典型的用例是在测试阶段注入模拟实现。

interface IA
{
  public void someFunction();
}


class B implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someBfunc()
  {
     //doing b things
  }
}


class C implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someCfunc()
  {
     //doing C things
  }
}

class MyRunner
{
     @Autowire
     @Qualifier("b") 
     IA worker;

     ....
     worker.someFunction();
}

您的 Bean 配置应如下所示:

<bean id="b" class="B" />
<bean id="c" class="C" />
<bean id="runner" class="MyRunner" />

或者,如果在存在这些组件的包上启用了组件扫描,则应按如下方式限定每个类:@Component

interface IA
{
  public void someFunction();
}

@Component(value="b")
class B implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someBfunc()
  {
     //doing b things
  }
}


@Component(value="c")
class C implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someCfunc()
  {
     //doing C things
  }
}

@Component    
class MyRunner
{
     @Autowire
     @Qualifier("b") 
     IA worker;

     ....
     worker.someFunction();
}

然后在 中将注入一个类型的实例。workerMyRunnerB


答案 2

此外,它还可能导致日志中的一些警告,例如Cglib2AopProxy无法代理方法。这里描述了许多其他原因,为什么在服务和dao层中总是有单一的实现接口?


推荐