Spring: pourquoi autowire l'interface et pas la classe implémentée?

exemple

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

quelqu'un peut-il me l'expliquer?

  • Comment ne ressort savoir quel type polymorphe à utiliser.
  • ai-je besoin de @Qualifier ou @Resource ?
  • pourquoi autorwire l'interface et pas la classe implémentée?
99
demandé sur stackoverflow 2012-10-15 19:53:59

2 réponses

comment spring sait quel type polymorphe utiliser.

aussi longtemps qu'il n'y a qu'une seule implémentation de l'interface et que cette implémentation est annotée par @Component avec la composante scan de Spring activée, Spring framework peut trouver la paire (interface, implémentation). Si le scan de component n'est pas activé, alors vous devez définir explicitement le bean dans votre application-config.xml (ou un ressort équivalent) fichier de configuration).

ai-je besoin de @qualificatif ou @Resource?

une fois que vous avez plus d'une implémentation, alors vous devez qualifier chacune d'entre elles et pendant l'auto-câblage, vous devez utiliser l'annotation @Qualifier pour injecter la bonne implémentation, avec l'annotation @Autowired . Si vous utilisez @Resource( sémantique J2EE), alors vous devez spécifier le nom du haricot en utilisant l'attribut name de cette annotation.

pourquoi autowire l'interface et pas la classe implémentée?

Premièrement, il est toujours bon de coder les interfaces en général. Deuxièmement, en cas de printemps, vous pouvez injecter n'importe quelle implémentation à l'exécution. Un cas d'utilisation typique est d'injecter une simulation de mise en œuvre au cours de la phase de test.

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

votre configuration de haricots devrait ressembler à ceci:

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

Sinon, si vous avez activé la fonction component scan sur le paquet où ils sont présents, vous devez qualifier chaque classe avec @Component comme suit:

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

puis worker dans MyRunner seront injectés avec une instance de type B .

161
répondu Vikdor 2012-10-15 16:39:18

aussi, il peut causer des warnigs dans les journaux comme un Cglib2AopProxy méthode incapable de proxy . Et beaucoup d'autres raisons pour cela sont décrites ici Pourquoi toujours avoir des interfaces d'implémentation uniques dans les couches service et dao?

1
répondu stokito 2015-09-22 11:29:38