@Qualifier
@Qualifier 可以让程序员明确指明需要那个bean,我们直接看代码
User类
public interface User {
}
User1类
@Component
public class User1 implements User{
}
User2类
@Component
public class User2 implements User{
}
UserService类
@Component
public class UserService {
@Autowired
private User user;
public void test() {
System.out.println(user);
}
}
DemoApplication类main方法
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.shadow.anno.demo");
UserService userService = applicationContext.getBean(UserService.class);
userService.test();
}
运行后我们会看到如下错误信息
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'user'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.shadow.anno.demo.User' available: expected single matching bean but found 2: user1,user2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:598)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:376)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1404)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:860)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:101)
at com.shadow.anno.demo.DemoApplication.main(DemoApplication.java:13)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.shadow.anno.demo.User' available: expected single matching bean but found 2: user1,user2
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:221)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1249)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1191)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:595)
... 14 more
这是由于我们程序中User类有User1和User2类两个实现,spring注入时会找到多个bean,于是报错,这里我们可以有集中解决方案:
- 给User1或User2类添加@Primary(这里在User1上添加,便于区分)
@Component
@Primary
public class User1 implements User{
}
我们运行后看到可以正常打印user的值,值为User1对象的实例
- 给UserService的user属性添加@Qualifier(这里用user2),并标明要使用的beanName,修改后如下代码
@Component
public class UserService {
@Autowired
@Qualifier("user2")
private User user;
public void test() {
System.out.println(user);
}
}
我们运行后看到可以正常打印user的值,值为User2对象的实例
@Autowired
@Autowired注入是先byType,如果找到多个bean之后再进行byName,也就是说,他优先根据类型进行注入,当找到多个bean时,再根据name来进行注入,它是由Spring提供的注解,由AutowiredAnnotationBeanPostProcessor类来解析的,解析代码在postProcessMergedBeanDefinition方法中,他可以写在构造方法、普通方法(静态方法无效)、方法参数、属性(静态属性无效)、注解上
@Resource
@Resource注入是byName,它是由jdk提供的注解,由CommonAnnotationBeanPostProcessor类来解析,解析代码在postProcessMergedBeanDefinition方法中,他可以写在类、普通方法(静态方法无效)、属性(静态属性无效)上