本文主要是介绍Spring处理自动装配歧义,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Spring处理自动装配歧义 由David发表在天码营
自动装配中冲突
自动装配(autowiring)要求bean的匹配具备唯一性,否则就会产生歧义,从而抛出异常。
例如,如果我们给QunarBookingService
和CtripBookingService
都标注上@Component
,则应用上下文中会有两个BookingService
实例。
QunarBookingService.java
@Component
package com.tianmaying.iocdemo;public class QunarBookingService implements BookingService {public void bookFlight() {System.out.println("book fight by Qunar!");}
}
CtripBookingService.java
@Component
package com.tianmaying.iocdemo;public class CtripBookingService implements BookingService {public void bookFlight() {System.out.println("book fight by Ctrip!");}
}
在SmartBoss
的代码中用@Autowired
标准的bookingService
属性,那么当Spring进行装配时,注入哪一个实现BookingService
接口的Bean就会面临多个选择。Spring就会抛出异常NoUniqueBeanDefinitionException
。
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tianmaying.dao.UserDao com.tianmaying.service.UserService.userDao; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tianmaying.dao.UserDao] is defined: expected single matching bean but found 2: userDaoImpl,userMemoryRepositoryat org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]... 43 common frames omitted
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tianmaying.dao.UserDao] is defined: expected single matching bean but found 2: userDaoImpl,userMemoryRepositoryat org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]... 45 common frames omitted
通过优先级
在定义bean时,可以通过@Primary
指定一个优先级高的bean来消除自动装配过程中遇到的歧义问题。
比如,如果SmartBoos
希望使用QunarBookingService
的实例,那么我们可以给其增加一个@Primary
标注。
QunarBookingService.java
@Component
@Primary
package com.tianmaying.iocdemo;public class QunarBookingService implements BookingService {public void bookFlight() {System.out.println("book fight by Qunar!");}
}
@Primary
作用在类上适用于自动装配。也可以通过XML配置或者Java配置的方式实现@Primary
标注的功能。
如果使用基于XML文件的显式配置,则可以如下定义:
<bean id="qunarBookingService"class="com.tianmaying.iocdemo.QunarBookingService"primary="true" />
如果使用基于XML文件的显式配置,则可以如下定义:
@Bean
@Primary
public QunarBookingService qunarBookingService() {return new QunarBookingService();
}
通过Qualifier
@Qualifier
注解可以跟@Autowired
或@Inject
一起使用,指定被注入的bean的ID。
每个Bean都有一个默认的Qualifier,内容与Bean的ID相同。
比如,我们也可以这样修改SmartBoss
的代码:
package com.tianmaying.iocdemo;...@Component
public class SmartBoss {private BookingService bookingService;@Autowired@Qualifier('qunarBookingService')public void setBookingService(BookingService bookingService) {this.bookingService = bookingService;}...
}
这样就告诉Spring给SmartBoss
注入Qualifer为qunarBookingService
的Bean。
我们也可以自定义Bean的Qualifier。在使用自定义的@Qualifier值时,最好选择一个含义准确意义明确的词。
更多文章请访问天码营网站
这篇关于Spring处理自动装配歧义的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!