自动装配
以上演示的这些例子全都是手动来实现一个bean的装配的,需要手动一个个去写
Spring中提供了三种装配的方式:
- 在xml中显式的配置
- 在java中显式的配置
- 隐式的自动装配
1. byName的装配方式
示例场景:
Spring容器中包含两个bean
一个son,一个father
其中father中包含一个son的属性,这里演示使用
这里先列出示例代码:
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="son" class="cc.leeleo.entity.Son">
<property name="name" value="erzi"/>
</bean>
<bean id="father" class="cc.leeleo.entity.Father">
<property name="name" value="baba" />
<property name="son" ref="son" />
</bean>
</beans>
Father.java 由于我们需要给装配一个son的变量,所以在Father增加了setSon()方法用于注入
public class Father {
private String name;
private Son son;
public void saySon(){
System.out.println(this.name+"说:erzi");
}
public void setName(String name) {
this.name = name;
}
public void setSon(Son son) {
this.son = son;
}
public Son getSon() {
return son;
}
}
Son.java
public class Son {
private String name;
public void sayDaddy(){
System.out.println(this.name+"说:baba");
}
public void setName(String name) {
this.name = name;
}
}
好了 重点来了,
原先在beans.xml中我们可以看到在注入son这个对象的时候,我们需要通过ref属性来指定要注入的bean。
现在我们可以通过Spring提供的auto wired属性来省去这一步。

我们看到bean标签的autowire的属性中包含五个值,
- byName顾名思义,Spring容器可以通过名称(bean的id、别名)去上下文中查找到对应id的bean将其装配
- byType顾名思义,Spring容器可以通过类型(bean的class)去上下文中查找到对应类型的bean将其装配。
- byConstructor顾名思义,可以通过(bean的constructor)查找相似构造器的方式来实现自动装配。
这里方便演示我们暂且只将byName和byType
首先我们先删除bean中如以下属性
~~<**property name~="son" ref="son"** />~~
并bean中加入该属性**autowire="byName"**
完整代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="son" class="cc.leeleo.entity.Son">
<property name="name" value="erzi"/>
</bean>
<bean id="father" class="cc.leeleo.entity.Father" autowire="byName">
<property name="name" value="baba" />
</bean>
</beans>
接下来我们测试一下

可以看到由于我们定义的Father类中的Son的set方法名称setSon和beans中定义的bean id = “son”一致,所以装配成功,我们再试下更改bean的id

此时我们发现,由于spring找不到装配时所需的set方法,此时为了验证其到底是不是根据set方法装配,我们将setSon方法更改为setSon1再来看下

此时便验证了我们之前所说,使用byName方式Spring会
根据需要装配的bean的set方法后的id值,去查找上下文中包含该id的bean进行装配
需要注意的是 使用byName的方式需要保证装配bean的id是唯一的,并且这个bean需要和注入属性的set方法名的值一致
2. byType的装配方式
这里我们更改**autowire="byType" ,**再试一下,使用此种方式可以将bean中的id属性干掉不用

由此得知,使用byType方式
Spring会在上下文中,根据需要装配的对象类型,在上下文中查找对应类型的bean进行装配
通过这两种方式都能完成对bean中所包含的对象进行装配,但是有利有弊
-
利:能省去xml中的配置代码,无需手动再去配置注入对象
<property name~=“son” ref=“son” /> -
弊:在开发过程中,我们并不能直观的从
的配置中看到注入的类是谁,需要到单独到bean所对应的类中去查看
需要注意的是 使用byType的方式需要保证装配的bean的类上下文中是唯一的
3. 使用注解的装配方式
在使用了上面两种方式进行装配以后,虽然是便利了些,但是还是差点意思,Spring 还提供了一种更爽的配置方式,注解!
jdk1.5支持的注解,Spring2.5就支持注解了使用注解须知:
- 导入约束:context约束
- 配置注解的支持:context:annotation-config/

完整示例:
beans.xml 这里我们添加上面的三个步骤,并且添加两个bean,这里细心的小伙伴们可能就发现了,咱们bean里面只有一个class属性,id和autowire都干掉了,代码又干净了不少。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解支持-->
<context:annotation-config/>
<bean class="cc.leeleo.entity.Son">
<property name="name" value="erzi"/>
</bean>
<bean class="cc.leeleo.entity.Father">
<property name="name" value="baba"/>
</bean>
</beans>
Father.java 这里我们把setSon的方法干掉!并且在son属性上加上@Autowired注解
public class Father {
private String name;
@Autowired
private Son son;
public void saySon(){
System.out.println(this.name+"说:erzi");
}
public void setName(String name) {
this.name = name;
}
public Son getSon() {
return son;
}
}
上面的代码是不是又简洁了不少?接下来我们再测试下

成功执行~
@Autowired 可以在属性上使用 也可以在set方法上使用,使用该方式可以省略set方法
4. Qualifier 注解
跟@Autowired一起使用的注解还有@Qualifier 注解,它的使用场景是,当一个spring的容器中存在多个相同类型的bean,这里就可以指定你使用哪个bean作为注入的对象
还是上面的代码,这里我们更改一下Fater类,增加@Qualifier注解,指定注入的bean为son2
public class Father {
private String name;
@Autowired
@Qualifier(value = "son2")
private Son son;
public void saySon(){
System.out.println(this.name+"说:erzi");
}
public void setName(String name) {
this.name = name;
}
public Son getSon() {
return son;
}
}
还有beans.xml,新增一个bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解支持-->
<context:annotation-config/>
<bean class="cc.leeleo.entity.Son">
<property name="name" value="erzi"/>
</bean>
<bean id="son2" class="cc.leeleo.entity.Son">
<property name="name" value="xiaoerzi"/>
</bean>
<bean class="cc.leeleo.entity.Father">
<property name="name" value="baba"/>
</bean>
</beans>
测试:

需要注意的是,
@Qualifier的value值指定的是Spring上下文中存在的bean的id
5. @Resource注解
除了Spring提供的@Autowired注解以外,java也提供了一个@Resource注解能实现相同的功能,这里我们废话不多说 上代码:
beans.xml 这里我们不做修改
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解支持-->
<context:annotation-config/>
<bean class="cc.leeleo.entity.Son">
<property name="name" value="erzi"/>
</bean>
<bean class="cc.leeleo.entity.Father">
<property name="name" value="baba"/>
</bean>
</beans>
Father.java 这里我们使用@Resource注解
public class Father {
private String name;
@Resource
private Son son;
public void saySon(){
System.out.println(this.name+"说:erzi");
}
public void setName(String name) {
this.name = name;
}
public Son getSon() {
return son;
}
}
测试:

如果有多个相同类型的bean,我们也可以通过@Resource(name = “xxx”)来指定所需的bean,
上代码:
Father.java 修改注解,指定name值为xml中bean的id
@Resource(name = "son2")
private Son son;
beans.xml 新增一个bean
<bean id="son2" class="cc.leeleo.entity.Son">
<property name="name" value="xiaoerzi"/>
</bean>
测试:

依旧没有问题~
- @Autowired和@Resource区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过byType实现,必须要求这个对象存在
- @Resoutce默认通过byName方式实现,如果找不到名字,则通过byType实现
- 执行顺序不同:@Autowired通过byType实现,@Resoutce通过byName实现