Person.java
@Controller
public class Person
{
@Autowired
private Ability ability;
public void printMessage(){
ability.printMessasge();
}
public void setOutputGenerator( Ability ability) {
this.ability = ability;
}
}
Ability.java
@Controller
public class Ability
{
void printMessasge(){
System.out.println("I print message");
}
}
spring.xml
<bean id="invisible" class="com.mkyong.common.Ability" >
</bean>
<context:component-scan base-package="com.mkyong" />
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( );
}
在上面的示例中,我使用Ability
和@Controller
文件中的一个定义了xml
第一类的两个bean。根据{{1}}类型我应该得到
Autowire
但我得到了正确的输出。为什么呢?
如果我创建一个Ability类实现的接口,那么我会得到UnsatisfiedDependencyException异常。像这样:
Parent.java
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException:
...
No unique bean of type [com.mkyong.common.Ability] is defined:
Ability.java
public interface Parent{
public void printMessasge();
}
Person.java
@Controller
public class Ability implements Parent
{
void printMessasge(){
System.out.println("I print message");
}
答案 0 :(得分:3)
默认情况下,Spring确实按类型匹配,但是在多个匹配bean的情况下,它会回退到按名称匹配。引用(6.9.4 Fine-tuning annotation-based autowiring with qualifiers)表示:
对于后备匹配,bean名称被视为默认限定符值。
使用@Qualifier
注释可以按类型进行自动装配,另外还可以通过名称更加明确。
答案 1 :(得分:2)
你不会得到UnsatisfiedDependencyException
这个配置,因为Spring足够智能,也可以查看所需依赖项的名称,正如@Adam在他的回答中写道的那样。因此,即使默认的自动装配模式是按类型,并且该依赖项有两个相同类型的bean,Spring也能够解决冲突。
官方文档6.9.4 Fine-tuning annotation-based autowiring with qualifiers部分介绍了此行为。 有关自动装配模式的更多详细信息,请参见6.4.5 Autowiring collaborators。
如果您将Person.ability字段的名称更改为其他内容,例如Person.ability2,那么Spring将抛出org.springframework.beans.factory.NoUniqueBeanDefinitionException
。它无法决定应该为Person.ability2字段连接哪个bean,因为:
com.mkyong.common.Ability
类型的bean 编辑:在你提到的第二种情况下(使用界面),Spring抛出了我上面解释的相同bean命名原因的异常。
官方文件参考:
答案 2 :(得分:0)
你定义了两个不明确的bean,当spring尝试通过类型找到bean时,它会找到两个bean,一个是通过扫描,另一个是在spring.xml中明确定义的。使用@Qualifier标记Person类中加载的正确bean。所以你可能想要这样,
@Controller
public class Person
{
@Autowired
@Qualifier("invisible")
private Ability ability;
public void printMessage(){
ability.printMessasge();
}
public void setOutputGenerator( Ability ability) {
this.ability = ability;
}
}