Spring @Qualifier 注解与示例
Spring 是最流行的Java EE 框架之一。它是一个开源轻量级框架,允许Java EE 7 开发人员构建简单、可靠且可扩展的企业应用程序。该框架主要侧重于提供各种方法来帮助您管理业务对象。与Java数据库连接 (JDBC)、JavaServer Pages (JSP) 和Java Servlet 等经典Java框架和应用程序编程接口 (API) 相比,它使 Web 应用程序的开发更加容易。该框架使用各种新技术,如面向方面编程 (AOP)、普通Java对象 (POJO) 和依赖注入 (DI) 来开发企业应用程序。现在谈论 Spring Annotation
Spring Annotations are a form of metadata that provides data about a program. Annotations are used to provide supplemental information about a program. It does not have a direct effect on the operation of the code they annotate. It does not change the action of the compiled program.
Spring 中最重要的注解之一是 @Qualifier 注解,用于消除需要注入哪个 bean 的问题。让我们通过一个例子来理解这一行。
Note: It is highly recommended that you need first understand the Spring @Autowired Annotation before jumping into @Qualifier Annotation.
执行:
让我们首先了解@Autowired Annotation 的问题,然后我们将了解为什么要引入@Qualifier Annotation。所以首先让我们创建一个名为Human的类,并且 Human 类确实依赖于另一个名为Heart的类。
一个文件: 人类。Java
Java
public class Human {
private Heart heart;
}
Java
public class Heart {
public void pump() {
System.out.println("Heart is Pumping");
}
}
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(); }
}
XML
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();
}
}
XML
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(); }
}
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(); }
}
B文件: 心。Java
这个类只有一个名为pump() 的简单方法。
Java
public class Heart {
public void pump() {
System.out.println("Heart is Pumping");
}
}
现在我们要使用 @Autowired 注解将 Heart 类的对象注入到 Human 类中。所以对于这个东西,我们可以这样写代码
例子
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文件: 豆类.xml
所以在beans.xml文件中,我们可以这样写代码
XML
D应用类
在主类中,我们可以编写类似这样的代码
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();
}
}
输出:
Heart is Pumping
输出说明:
所以上面的代码执行得很好。现在让我们简单解释一下上面代码中发生的事情。因此,每当您在 Human 类的 setter 方法之前放置 @Autowired 注释时,这将通过使用Spring Autowiring 'byType'的机制将 Heart 类的对象自动装配到 Human 类中。
Note: How @Autowired Work?
- First, it tries to resolves with “byType”.
- If “byType” fails then it goes with “byName”.
所以在我们上面的例子中,“byType”Spring Autowiring 机制发生了,heart 对象被注入到 Human 类中。但问题出在哪里?现在在beans.xml文件中,让我们创建 Heart 类的另一个 bean。我们可以像这样编写代码。现在我们修改后的beans.xml文件是
XML
这里我们有两个相同类的bean,一个是“humanHeart”,另一个是“octpusHeart”。所以在那种情况下,“byType”和“byName”Spring Autowiring 都会失败。因为同一类 Heart 有两个 bean,并且 id 与对象“heart”不匹配。因此,每当您要运行应用程序时,都会遇到以下异常。
这就是@Qualifier Annotation 发挥作用的地方。因此,每当“byType”和“byName” Spring Autowiring 都将失败时,我们可以在 setter 方法之前使用 @Qualifier 注解,并且可以在其中提及 bean id。例如,在 Human 类的情况下,我们需要“humanHeart” bean,因此我们可以在 @Qualifier Annotation 中提及该 bean。所以我们可以写这样的东西来解决这个错误。
示例:修改后的 Human.class 文件
Java
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)
输出:
// 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(); }
}
一件更有趣的事情是我们还可以在依赖项之前使用这些注解。不需要任何 setter 方法。所以我们也可以写这样的东西。
Java
Heart is Pumping
Conclusion: Spring @Autowired Annotation first looks for “byType” if there is any conflict then it is going to look for “byName”. And if any conflict with “byName”, resolve that with @Qualifier Annotation.