Primavera: Perché autorichiamo l'interfaccia e non la classe implementata?


142

Esempio

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

Qualcuno può spiegarmelo.

  • Come fa la primavera a sapere quale tipo polimorfico usare.
  • Ho bisogno @Qualifiero @Resource?
  • Perché autorichiamo l'interfaccia e non la classe implementata?

10
Autorizzi l'interfaccia in modo da poter collegare un'implementazione diversa : questo è uno dei punti di codifica per l'interfaccia, non la classe.
Dave Newton,

Collegheresti un'implementazione diversa; Non capisco la domanda.
Dave Newton,

Se eseguiamo il cablaggio nell'interfaccia, cosa succede quando esiste un metodo di visibilità predefinito all'interno della classe Impl a cui devo accedere? Non riesco ad aggiungere quel metodo stub all'interfaccia perché l'interfaccia pubblica non può contenere modificatore predefinito.
jlewkovich,


1
Penso che creare un'interfaccia per una sola implementazione sia una pratica stupida accettata nel mondo Java. Il risultato è un sacco di codice garbage, ma tutti sono felici di aver seguito le regole di SOLID e OOP. Usa l'abilità e lancia la molla nella pattumiera della storia.
avgolubev,

Risposte:


224

Come fa la primavera a sapere quale tipo polimorfico usare.

Finché esiste una sola implementazione dell'interfaccia e tale implementazione è annotata con @Componentla scansione dei componenti di Spring abilitata, il framework Spring può scoprire la coppia (interfaccia, implementazione). Se la scansione dei componenti non è abilitata, è necessario definire esplicitamente il bean in application-config.xml (o file di configurazione di primavera equivalente).

Ho bisogno di @Qualifier o @Resource?

Una volta che hai più di un'implementazione, devi qualificarle ognuna e durante il cablaggio automatico, dovrai usare l' @Qualifierannotazione per iniettare l'implementazione giusta, insieme @Autowiredall'annotazione. Se si utilizza @Resource (semantica J2EE), è necessario specificare il nome del bean utilizzando l' nameattributo di questa annotazione.

Perché autorichiamo l'interfaccia e non la classe implementata?

In primo luogo, è sempre una buona pratica programmare codice per le interfacce in generale. In secondo luogo, in caso di primavera, è possibile iniettare qualsiasi implementazione in fase di esecuzione. Un caso d'uso tipico è quello di iniettare un'implementazione simulata durante la fase di 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 configurazione del tuo bean dovrebbe apparire così:

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

In alternativa, se hai abilitato la scansione dei componenti sul pacchetto in cui sono presenti, allora dovresti qualificare ciascuna classe @Componentcome segue:

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

Poi workerin MyRunnerverrà iniettato con un'istanza di tipo B.


@stackoverflow Modificare la domanda non avrebbe alcun senso, il nuovo codice appartiene alla risposta. Altrimenti la domanda non ha senso, perché avrebbe risposto da sola.
Dave Newton,

Vikdor - vedi modifica. È questo il modo corretto di annotare le classi e l'oggetto iniettato?
StackOverflow

1
@VictorDombrovsky È @Autowired @Qualifier("a1") a;valido?
Lucky

1
@Lucky ho fatto un errore. Intendevo@Autowired @Qualifier("a1") A a;
Victor Dombrovsky il

1
È anche possibile utilizzare @Profile sull'implementazione per controllare quale implementazione deve essere iniettata per quell'interfaccia tramite argomenti del programma o proprietà dell'applicazione.
b15,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.