Como Spring autowire por nome quando mais de um bean correspondente é encontrado?

106

Suponha que eu tenha interfaces como estas:

interface Country {}
class USA implements Country {}
class UK implements Country ()

E este snippet de configuração xml:

<bean class="USA"/>
<bean id="country" class="UK"/>
<bean id="main" class="Main"/>

Como posso controlar qual dependência é autowired abaixo? Eu gostaria do Reino Unido.

class Main {
    private Country country;
    @Autowired
    public void setCountry(Country country) {
        this.country = country;
    }
}

Estou usando o Spring 3.0.3.RELEASE.

Maniganda Prakash
fonte
Pensei em acrescentar que estava obtendo um "Nenhum bean exclusivo do tipo ..." em um ambiente (de teste) e funcionou bem no meu ambiente de desenvolvimento. Tenho certeza de que era algum tipo de classpath, mas descobri que, se você adicionar @Qualifier, funcionou bem.
markthegrea

Respostas:

113

Isso está documentado na seção 3.9.3 do manual Spring 3.0:

Para uma correspondência de fallback, o nome do bean é considerado um valor de qualificador padrão.

Em outras palavras, o comportamento padrão é como se você tivesse adicionado @Qualifier("country")ao método setter.

skaffman
fonte
Quando você diz "nome do bean", você quer dizer o nome do campo que conterá o bean? (ou seja, neste caso country)
Processo de financiamento de Monica de
67

Você pode usar a anotação @Qualifier

A partir daqui

Ajuste automático baseado em anotações com qualificadores

Como o autowiring por tipo pode levar a vários candidatos, muitas vezes é necessário ter mais controle sobre o processo de seleção. Uma maneira de fazer isso é com a anotação @Qualifier do Spring. Isso permite associar valores de qualificador a argumentos específicos, estreitando o conjunto de correspondências de tipo para que um bean específico seja escolhido para cada argumento. No caso mais simples, pode ser um valor descritivo simples:

class Main {
    private Country country;
    @Autowired
    @Qualifier("country")
    public void setCountry(Country country) {
        this.country = country;
    }
}

Isso usará o Reino Unido, adicionará uma id ao bean dos EUA e usará se você quiser os EUA.

Paul Whelan
fonte
12

Outra maneira de obter o mesmo resultado é usar a anotação @Value:

public class Main {
     private Country country;

     @Autowired
     public void setCountry(@Value("#{country}") Country country) {
          this.country = country;
     }
}

Nesse caso, a "#{country}string é uma expressão Spring Expression Language (SpEL) que avalia como um bean denominado country.

Ricardo Veguilla
fonte
isso pode ser injetado com base na propriedade? e se EUA ou Reino Unido forem algum tipo de parâmetro vindo de URL e eu quiser injetar 2 coisas diferentes com base no parâmetro?
Kalpesh Soni
6

Mais uma solução para resolver por nome:

@Resource(name="country")

Ele usa o pacote javax.annotation , então não é específico do Spring, mas o Spring o suporta.

tema
fonte
1
mas @Resourcenão estará lá pronto para uso com o java 11 devido aos módulos do quebra-cabeças
Dirk Hoffmann