[英]Why i am not getting No unique bean of type in Autowiring in spring
Person.java 人.java
@Controller
public class Person
{
@Autowired
private Ability ability;
public void printMessage(){
ability.printMessasge();
}
public void setOutputGenerator( Ability ability) {
this.ability = ability;
}
}
Ability.java Ability.java
@Controller
public class Ability
{
void printMessasge(){
System.out.println("I print message");
}
}
spring.xml spring.xml
<bean id="invisible" class="com.mkyong.common.Ability" >
</bean>
<context:component-scan base-package="com.mkyong" />
App.java App.java
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"spring.xml");
Person person = (Person) context.getBean("person");
person.printMessage( );
}
In the above example i have defined two beans of Ability
class one using @Controller
and one in xml
file. 在上面的示例中,我定义了两个
Ability
类的bean,一个使用@Controller
,另一个在xml
文件中。 According to Autowire
by type i should get 根据
Autowire
的类型,我应该得到
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException:
...
No unique bean of type [com.mkyong.common.Ability] is defined:
But i am getting proper output. 但是我得到适当的输出。 Why?
为什么?
And if i create an interface which Ability class implements then i would get UnsatisfiedDependencyException exception. 如果我创建一个由Ability类实现的接口,那么我将得到UnsatisfiedDependencyException异常。 Like this:
像这样:
Parent.java Parent.java
public interface Parent{
public void printMessasge();
}
Ability.java Ability.java
@Controller
public class Ability implements Parent
{
void printMessasge(){
System.out.println("I print message");
}
Person.java 人.java
@Controller
public class Person
{
@Autowired
Parent parent;
public void printMessage(){
parent.printMessasge();
}
public void setOutputGenerator( Parent parent) {
this.parent= parent;
}
}
By default Spring indeed matches by type, but in case of multiple matching beans, it falls back to matching by name. 默认情况下,Spring确实按类型进行匹配,但是如果有多个匹配的Bean,它将回退到按名称进行匹配。 The reference ( 6.9.4 Fine-tuning annotation-based autowiring with qualifiers ) says:
参考资料( 6.9.4使用限定符微调基于注释的自动装配 )表示:
For a fallback match, the bean name is considered a default qualifier value.
对于后备匹配,bean名称被认为是默认的限定符值。
Using the @Qualifier
annotation makes the autowiring by type and additionally by name more explicit. 使用
@Qualifier
批注使按类型以及名称的自动装配更加明确。
You are not going to get a UnsatisfiedDependencyException
with this configuration because Spring is smart enough to also look at the name of your required dependency, as @Adam writes in his answer. 这种配置不会导致
UnsatisfiedDependencyException
,因为Spring非常聪明,还可以查看所需依赖项的名称,就像@Adam在他的回答中所写的那样。 So even if the default autowiring mode is by type and there are two beans of the same type for that dependency, Spring is able to solve the conflict. 因此,即使默认的自动装配模式是按类型,并且对于该依赖项有两个相同类型的bean,Spring也能够解决冲突。
This behavior is described in the official documentation, 6.9.4 Fine-tuning annotation-based autowiring with qualifiers section. 官方文档6.9.4中的“使用限定符对基于注释的自动装配进行微调”部分对此行为进行了描述。 More details about autowiring modes can be found 6.4.5 Autowiring collaborators .
有关自动装配模式的更多详细信息,请参见6.4.5自动装配协作器 。
If you change the name of Person.ability field to something else, like Person.ability2, then Spring will throw a org.springframework.beans.factory.NoUniqueBeanDefinitionException
. 如果将Person.ability字段的名称更改为其他名称,例如Person.ability2,那么Spring将抛出
org.springframework.beans.factory.NoUniqueBeanDefinitionException
。 It cannot decide which bean it should wire for the Person.ability2 field because: 它不能决定应为Person.ability2字段连接哪个bean,因为:
com.mkyong.common.Ability
type in the context com.mkyong.common.Ability
类型的两个bean EDIT: in the second case you mention (with the interface), Spring throws the exception for the same bean naming reason I explained above. 编辑:在第二种情况下,您提到(使用接口),Spring会出于与我上面解释的相同的bean命名原因而引发异常。
Official documentation references: 官方文档参考:
you have two ambiguous beans defined, when spring try find the bean via type it finds two beans, one via scan other explicitly defined in spring.xml. 您定义了两个模糊的bean,当spring尝试通过类型查找bean时,它会找到两个bean,一个通过scan其他在spring.xml中显式定义的bean。 use @Qualifier to mark the correct bean loaded in Person class.
使用@Qualifier标记在Person类中加载的正确bean。 So probably you want like this,
所以大概你想要这样,
@Controller
public class Person
{
@Autowired
@Qualifier("invisible")
private Ability ability;
public void printMessage(){
ability.printMessasge();
}
public void setOutputGenerator( Ability ability) {
this.ability = ability;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.