Primavera: Por que ligamos automaticamente a interface e não a classe implementada?


142

Exemplo

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

Alguém pode me explicar isso.

  • Como a primavera sabe qual tipo polimórfico usar.
  • Eu preciso @Qualifierou@Resource ?
  • Por que conectamos automaticamente a interface e não a classe implementada?

10
Você conecta automaticamente a interface para poder conectar em uma implementação diferente - esse é um dos pontos de codificação para a interface, não para a classe.
Dave Newton

Você conectaria uma implementação diferente; Eu não entendo a pergunta.
Dave Newton

Se estivermos conectando a interface, o que acontece quando há um método de visibilidade padrão na classe Impl à qual preciso acessar? Não consigo adicionar esse stub de método à interface porque a interface pública não pode conter modificador padrão.
jlewkovich


1
Eu acho que fazer uma interface para apenas uma implementação é uma prática estúpida que é aceita no mundo java. O resultado é muito código de lixo, mas todos estão felizes por terem seguido as regras do SOLID e do OOP. Use o truque e jogue a primavera na lata de lixo da história.
Avgolubev 21/12/19

Respostas:


224

Como a primavera sabe qual tipo polimórfico usar.

Desde que haja apenas uma única implementação da interface e essa implementação seja anotada com @Componenta verificação de componente do Spring ativada, a estrutura do Spring pode descobrir o par (interface, implementação). Se a varredura de componentes não estiver ativada, você deverá definir explicitamente o bean no seu application-config.xml (ou arquivo de configuração equivalente da primavera).

Preciso de @Qualifier ou @Resource?

Depois de ter mais de uma implementação, você precisará qualificar cada uma delas e, durante a fiação automática, você precisará usar a @Qualifieranotação para injetar a implementação correta, juntamente com a @Autowiredanotação. Se você estiver usando @Resource (semântica J2EE), deverá especificar o nome do bean usando o nameatributo desta anotação.

Por que conectamos automaticamente a interface e não a classe implementada?

Em primeiro lugar, é sempre uma boa prática codificar para interfaces em geral. Em segundo lugar, no caso da primavera, você pode injetar qualquer implementação em tempo de execução. Um caso de uso típico é injetar implementação simulada durante o estágio de teste.

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

Sua configuração de bean deve ficar assim:

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

Como alternativa, se você ativou a varredura de componentes no pacote em que estes estão presentes, você deve qualificar cada classe da @Componentseguinte maneira:

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

Em seguida, workerem MyRunnervai ser injectado com uma instância do tipo B.


@stackoverflow A edição da pergunta não faria sentido, o novo código pertence à resposta. Caso contrário, a pergunta não faz sentido, porque teria respondido a si mesma.
Dave Newton

Vikdor - por favor, veja editar. Essa é a maneira correta de anotar as classes e o objeto injetado?
stackoverflow

1
@VictorDombrovsky É @Autowired @Qualifier("a1") a;válido?
Lucky

1
@ Sorte que cometi um erro. Eu quis dizer@Autowired @Qualifier("a1") A a;
Victor Dombrovsky

1
Você pode até usar o @Profile na implementação para controlar qual implementação deve ser injetada para essa interface por meio de argumentos do programa ou propriedades do aplicativo.
b15

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.