Anotación Spring @Qualifier con ejemplo

Spring es uno de los marcos Java EE más populares. Es un marco ligero de código abierto que permite a los desarrolladores de Java EE 7 crear aplicaciones empresariales sencillas, fiables y escalables. Este marco se centra principalmente en proporcionar varias formas de ayudarlo a administrar sus objetos comerciales. Hizo que el desarrollo de aplicaciones web fuera mucho más fácil en comparación con los marcos Java clásicos y las interfaces de programación de aplicaciones (API), como la conectividad de base de datos Java (JDBC), JavaServer Pages (JSP) y Java Servlet. Este marco utiliza varias técnicas nuevas, como la programación orientada a aspectos (AOP), el objeto Java antiguo simple (POJO) y la inyección de dependencia (DI), para desarrollar aplicaciones empresariales. Ahora hablando de Spring Annotation

Las anotaciones de Spring son una forma de metadatos que proporcionan datos sobre un programa. Las anotaciones se utilizan para proporcionar información complementaria sobre un programa. No tiene un efecto directo sobre el funcionamiento del código que anotan. No cambia la acción del programa compilado. 

Una de las anotaciones más importantes en Spring es la anotación @Qualifier, que se utiliza para eliminar el problema de qué bean debe inyectarse . Entendamos esta línea con un ejemplo. 

Nota: Se recomienda encarecidamente que primero comprenda la anotación Spring @Autowired antes de pasar a la anotación @Qualifier.

Implementación: 

Primero entendamos el problema con la anotación @Autowired y luego entenderemos por qué se introdujo la anotación @Qualifier. Así que primero vamos a crear una clase llamada Human y la clase Human depende de otra clase llamada Heart

Un archivo:Humano.java

Java

public class Human {
    private Heart heart;
}

Archivo B : Corazón.java

Esta clase tiene solo un método simple llamado pump().

Java

public class Heart {
    public void pump() {
        System.out.println("Heart is Pumping");
    }
}

Ahora queremos inyectar el objeto de la clase Heart dentro de la clase Human usando la anotación @Autowired. Entonces, para esto, podemos escribir el código algo como esto

Ejemplo 

Java

// Java Program to Illustrate Injection of object of the
// Heart class inside the Human class using the @Autowired
// annotation
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
 
// Class
public class Human {
 
    private Heart heart;
 
    // Annotation
    @Autowired public void setHeart(Heart heart)
    {
        this.heart = heart;
    }
 
    // Method
    // Calling method of Heart class
    public void startPumping() { heart.pump(); }
}

C File:beans.xml
 Así que en el archivo beans.xml , podemos escribir el código algo como esto

XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:annotation-config/>
 
    <bean id="heartObjValue" class="Heart"></bean>
    <bean id="humanObject" class="Human"></bean>
  
</beans>

Clase de aplicación  D

Y en la clase principal, podemos escribir el código algo como esto

Java

// Java Program to Illustrate Application Class
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
// Application class
// Main class
public class Main {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating an new class path
        ApplicationContext context
            = new ClassPathXmlApplicationContext(
                "beans.xml");
        Human human
            = context.getBean("humanObject", Human.class);
        human.startPumping();
    }
}

Producción: 

Heart is Pumping

Explicación de salida

Así que el código anterior se ejecuta bien. Ahora veamos una breve explicación de lo que sucede en el código anterior. Entonces, cada vez que coloque una anotación @Autowired antes del método setter en la clase Human, esto conectará automáticamente el objeto de la clase Heart en la clase Human mediante el mecanismo de Spring Autowiring ‘byType’

Nota : ¿Cómo funciona @Autowired?

  1. Primero, intenta resolver con «byType».
  2. Si «byType» falla, entonces va con «byName».

Entonces, en nuestro ejemplo anterior, ocurre el mecanismo Spring Autowiring «byType» y el objeto del corazón se inyecta en la clase Human. Pero, ¿dónde está el problema? Ahora, dentro del archivo beans.xml , creemos otro bean de la clase Heart. Podemos escribir el código algo como esto. Ahora nuestro archivo  beans.xml modificado es

XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:annotation-config/>
 
    <bean id="humanHeart" class="Heart"></bean>
    <bean id="octpusHeart" class="Heart"></bean>
 
    <bean id="humanObject" class="Human"></bean>
 
</beans>

Aquí tenemos dos beans de la misma clase, uno es «humanHeart» y otro es «octpusHeart». Entonces, en ese escenario, tanto el cableado automático de resorte «por tipo» como «por nombre» fallarán. Porque hay dos beans para la misma clase Heart y la identificación no coincide con el objeto «heart». Entonces, cada vez que vaya a ejecutar su aplicación, obtendrá las siguientes excepciones.

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'humanObject': Unsatisfied dependency expressed through method 'setHeart' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'Heart' available: expected single matching bean but found 2: humanHeart,octpusHeart
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:768)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:720)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413)

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'Heart' available: expected single matching bean but found 2: humanHeart,octpusHeart
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1358)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)

Y aquí es donde entra en escena la anotación @Qualifier . Por lo tanto, cada vez que falle el cableado automático de Spring «byType» y «byName», podemos usar la anotación @Qualifier antes del método setter y podemos mencionar la identificación del bean dentro de eso. Por ejemplo, en el caso de la clase Human, necesitamos el bean «humanHeart», por lo que podemos mencionar ese bean dentro de la anotación @Qualifier. Entonces podemos escribir algo como esto para resolver este error.

Ejemplo: archivo Human.class modificado 

Java

// Java Program to Illustrate Modified Human Class
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
 
// Class
public class Human {
 
    private Heart heart;
 
    // Annotation
    @Autowired
    @Qualifier("humanHeart")
 
    // Setter
    public void setHeart(Heart heart)
    {
        this.heart = heart;
    }
 
    // Method
    public void startPumping() { heart.pump(); }
}

Producción:

Heart is Pumping

Una cosa más interesante es que también podemos usar estas anotaciones antes de la dependencia. No hay necesidad de ningún método setter. Entonces podemos escribir algo como esto también. 

Java

// Java Program to Illustrate Modified Human Class
// Where we used these annotations before the dependency
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
 
// Class
public class Human {
 
    @Autowired @Qualifier("humanHeart") private Heart heart;
 
    // Method
    public void startPumping() { heart.pump(); }
}

Conclusión: Spring @Autowired Annotation primero busca «byType», si hay algún conflicto, luego buscará «byName». Y si hay algún conflicto con «byName», resuélvalo con la anotación @Qualifier.

Publicación traducida automáticamente

Artículo escrito por AmiyaRanjanRout y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *