web-dev-qa-db-fra.com

Spring: Pourquoi connectons-nous automatiquement l'interface et non 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 m'expliquer cela.

  • Comment spring sait-il quel type polymorphe utiliser?.
  • Ai-je besoin de @Qualifier ou @Resource?
  • Pourquoi connectons-nous automatiquement l'interface et non la classe implémentée?
132
stackoverflow

Comment spring sait-il quel type polymorphe utiliser?.

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

Est-ce que j'ai besoin de @Qualifier ou de @Resource?

Une fois que vous avez plus d'une implémentation, vous devez ensuite qualifier chacune d'entre elles et, lors du câblage automatique, vous devez utiliser l'annotation @Qualifier pour injecter la bonne implémentation, ainsi que l'annotation @Autowired. Si vous utilisez @Resource (sémantique J2EE), vous devez alors spécifier le nom du bean à l'aide de l'attribut name de cette annotation.

Pourquoi connectons-nous automatiquement l'interface et non la classe implémentée?

Premièrement, il est toujours recommandé de coder les interfaces en général. Deuxièmement, en cas de ressort, vous pouvez injecter n'importe quelle implémentation au moment de l'exécution. Un cas d'utilisation typique consiste à injecter une implémentation fictive 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();
}

La configuration de votre bean devrait ressembler à ceci:

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

Si vous avez également activé l'analyse des composants sur le package contenant ces éléments, vous devez alors 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();
}

Ensuite, worker dans MyRunner recevra une instance de type B.

203
Vikdor

En outre, cela peut provoquer des avertissements dans les journaux comme un méthode Cglib2AopProxy impossible à proxy . Et bien d’autres raisons à cela sont décrites ici Pourquoi toujours des interfaces d’implémentation uniques dans les couches service et dao?

1
stokito