¿Cómo Spring se conecta automáticamente por nombre cuando se encuentra más de un bean coincidente?

106

Supongamos que tengo interfaces como estas:

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

Y este fragmento de configuración xml:

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

¿Cómo puedo controlar qué dependencia se conecta automáticamente a continuación? Me gustaría el del Reino Unido.

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

Estoy usando Spring 3.0.3.RELEASE.

Maniganda Prakash
fuente
Pensé que agregaría que estaba obteniendo un "No bean único de tipo ..." en un entorno (de prueba) y funcionó bien en mi entorno de desarrollo. Estoy seguro de que fue una especie de ruta de clase, pero resultó que, si agrega el @Qualifier, funcionó bien.
markthegrea

Respuestas:

113

Esto está documentado en la sección 3.9.3 del manual Spring 3.0:

Para una coincidencia alternativa, el nombre del bean se considera un valor calificador predeterminado.

En otras palabras, el comportamiento predeterminado es como si lo hubiera agregado @Qualifier("country")al método de establecimiento.

skaffman
fuente
Cuando dice "nombre del frijol", ¿se refiere al nombre del campo que contendrá el frijol? (es decir, en este caso country)
Financia la demanda de Monica el
67

Puede usar la anotación @Qualifier

Desde aqui

Ajuste del cableado automático basado en anotaciones con calificadores

Dado que el cableado automático por tipo puede conducir a múltiples candidatos, a menudo es necesario tener más control sobre el proceso de selección. Una forma de lograr esto es con la anotación @Qualifier de Spring. Esto permite asociar valores de calificador con argumentos específicos, reduciendo el conjunto de coincidencias de tipos para que se elija un bean específico para cada argumento. En el caso más simple, este puede ser un valor descriptivo simple:

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

Esto usará el Reino Unido para agregar una identificación al bean de EE. UU. Y usarlo si desea EE. UU.

Paul Whelan
fuente
12

Otra forma de lograr el mismo resultado es usar la anotación @Value:

public class Main {
     private Country country;

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

En este caso, la "#{country}cadena es una expresión de Spring Expression Language (SpEL) que se evalúa como un bean llamado country.

Ricardo Veguilla
fuente
¿Se puede inyectar en función de la propiedad? ¿Qué pasa si EE. UU. o Reino Unido es algún tipo de parámetro que proviene de la URL y quiero inyectar 2 cosas diferentes en función de cuál es el parámetro?
Kalpesh Soni
6

Una solución más con la resolución por nombre:

@Resource(name="country")

Utiliza el paquete javax.annotation , por lo que no es específico de Spring, pero Spring lo admite.

tema
fuente
1
pero @Resourceno estará listo para usar con java 11 debido a los módulos de rompecabezas
Dirk Hoffmann