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?
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
.
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?