春季:为什么我们要自动装配接口而不是实现的类?


142

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();
}

谁可以给我解释一下这个。

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

10
您可以自动连接接口,以便可以连接不同的实现-这是接口编码的要点之一,而不是类。
戴夫·牛顿

您将采用其他实现;我不明白这个问题。
戴夫牛顿

如果我们在接口中进行布线,当Impl类中需要访问默认的可见性方法时,会发生什么情况?我不能将该方法存根添加到接口中,因为公共接口不能包含默认修饰符。
jlewkovich


1
我认为仅为一种实现建立接口是一种愚蠢的做法,在Java世界中已被接受。结果是大量垃圾代码,但是每个人都满意他们遵循SOLID和OOP的规则。用向导把弹簧扔进历史的垃圾箱。
avgolubev

Answers:


224

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

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

我需要@Qualifier或@Resource吗?

一旦拥有多个实现,就需要对每个实现进行限定,并且在自动装配期间,您需要使用@Qualifier批注将正确的实现以及批注一起注入@Autowired。如果使用@Resource(J2EE语义),则应使用name此批注的属性指定Bean名称。

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

首先,一般来说,对接口进行编码始终是一个好习惯。其次,在spring的情况下,您可以在运行时注入任何实现。一个典型的用例是在测试阶段注入模拟实现。

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();
}

然后workerMyRunner中将注入type的实例B


@stackoverflow编辑问题没有任何意义,答案中包含新代码。否则,这个问题就没有意义了,因为它会回答自己。
戴夫牛顿

Vikdor-请参阅编辑。这是注释类和注入对象的正确方法吗?
stackoverflow 2012年

1
@VictorDombrovsky @Autowired @Qualifier("a1") a;有效吗?
幸运

1
@Lucky我弄错了。我的意思是@Autowired @Qualifier("a1") A a;
维克多Dombrovsky

1
您甚至可以在实现上使用@Profile,以通过程序参数或应用程序属性控制应为该接口注入哪个实现。
b15

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.