1 Spring 的装配机制
-
在 xml 中显式配置;
-
在 java 中显式配置;
-
隐式的 bean发现机制和自动装配
之前我们常用的便是第一种,在 xml 中显式配置,比如上一章中的依赖注入,接下来将介绍隐式的 bean发现机制和自动装配。
2 自动装配
根据需求来理解。
确定需求如下:在实验室类(Lab)中装配两个两个同学类(Sharm、Nola),使得在测试的时候可以直接通过 Lab 对象来输出同学的方法。
接下来对比 xml 手动装配和隐式的自动装配的区别。
2.1 xml 手动装配
1)创建两个同学类(Sharm、Nola)
public class Sharm {
public void show(){
System.out.println("My name is Sharm, do you know.");
}
}
public class Nola {
public void show(){
System.out.println("My name is Nola, do you know.");
}
}
2)创建一个包含(Sharm、Nola)属性的实验室类(Lab)
public class Lab {
public Sharm sharm;
public Nola nola;
public String admin;
public Lab() {
}
public Lab(Sharm sharm, Nola nola, String admin) {
this.sharm = sharm;
this.nola = nola;
this.admin = admin;
}
public Sharm getSharm() {
return sharm;
}
public void setSharm(Sharm sharm) {
this.sharm = sharm;
}
public Nola getNola() {
return nola;
}
public void setNola(Nola nola) {
this.nola = nola;
}
public String getAdmin() {
return admin;
}
public void setAdmin(String admin) {
this.admin = admin;
}
}
3)编写 Spring 配置文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="sharm" class="sharm.autowire.Sharm"/>
<bean id="nola" class="sharm.autowire.Nola"/>
<bean id="lab" class="sharm.autowire.Lab">
<property name="admin" value="Jalu"/>
<property name="sharm" ref="sharm"/>
<property name="nola" ref="nola"/>
</bean>
</beans>
4)测试
public class AutowireTest {
@Test
public void test(){
// 固定写法
ApplicationContext context = new ClassPathXmlApplicationContext("autowire.xml");
// 得到对象,其中参数为对象名
Lab lab = context.getBean("lab", Lab.class);
// 开始使用对应同学类的方法
lab.sharm.show();
lab.nola.show();
}
}
2.2 隐式的自动装配
两种自动装配的属性:
属性名 | 作用 |
---|---|
byName | 按照属性名自动装配,使用该属性后,会自动在容器上下文中查找和自己对象 setter 方法后面的值相同的 bean id。如果有,就取出注入,如果没有,就报(NullPointerException)空指针异常。 |
byType | 按照类型自动装配,使用该属性后,会自动在容器上下文中查找和自己对象类型相同的 bean。同时,在 Spring 容器中,同一类型的对象必须要唯一。 |
2.2.1 byName
保持三个实体类不变,修改 Spring 配置文件如下:
<bean id="sharm" class="sharm.autowire.Sharm"/>
<!-- 因为是按照 bean id 名来取对应的 bean 的,所以如果修改 id 值,则会导致自动注入失败-->
<bean id="nola_fail" class="sharm.autowire.Nola"/>
<!-- 所以必须使用下一种方式-->
<!-- <bean id="nola" class="sharm.autowire.Nola"/>-->
<!-- 使用 byName 或者 byType 只需要修改 bean 标签的 autowire 的值 -->
<bean id="lab" class="sharm.autowire.Lab" autowire="byName">
<property name="admin" value="Jalu"/>
</bean>
2.2.2 byType
<bean id="sharm" class="sharm.autowire.Sharm"/>
<!-- 因为是按照 bean 的类型来获取对应的 bean 的,所以如果就算 id 正确,但类错误,也会导致自动注入失败-->
<bean id="nola" class="sharm.autowire.Sharm"/>
<!-- 所以必须使用下一种方式-->
<!-- <bean id="nola" class="sharm.autowire.Nola"/>-->
<!-- 使用 byName 或者 byType 只需要修改 bean 标签的 autowire 的值 -->
<bean id="lab" class="sharm.autowire.Lab" autowire="byType">
<property name="admin" value="Jalu"/>
</bean>
3 使用注解实现自动装配
3.1 简介
注释名 | 配置 | 位置 | 作用 |
---|---|---|---|
@Autowired | 需要加入配置文件以及导入 jar 包 | 可以写在字段上,或写在setter方法上 | 根据类型自动装配的,如果想使用 byName 装配,则需要另外加上 @Qualifier 注解 |
@Resource | 不需要加入配置文件,需要导入 jar 包 | 可以写在字段上,或写在setter方法上 | 优先使用指定的name属性进行装配,其次使用 byName 装配,最后使用 byType 装配,如果都不成功,则报异常 |
3.2 @Autowired 自动装配
1)导入 spring-aop 包
2)修改 Spring 配置文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
修改成如下:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
3)修改实验室类(Lab)
在字段或者 setter 方法加上 @Autowired 注解
public class Lab {
@Autowired
public Sharm sharm;
@Autowired
// @Autowired(required = false) 字段不必须存对象
public Nola nola;
public String admin;
……
}
4)修改 Spring 配置文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="nola" class="sharm.autowire.Nola"/>
<bean id="sharm" class="sharm.autowire.Sharm"/>
<bean id="lab" class="sharm.autowire.Lab"/>
</beans>
5)当容器中包含多个 Sharm 对象时
因为 @Autowired 是根据类型自动装配的,如果当容器中包含多个 Sharm 对象时,则可以加上 @Qualifier 来根据 byName 的方式自动装配。
public class Lab {
@Autowired
@Qualifier(value = "cheatSharm")
public Sharm sharm;
@Autowired
public Nola nola;
public String admin;
……
}
<bean id="nola" class="sharm.autowire.Nola"/>
<bean id="sharm" class="sharm.autowire.Sharm"/>
<bean id="cheatSharm" class="sharm.autowire.Sharm"/>
<bean id="lab" class="sharm.autowire.Lab"/>
3.3 @Resource 自动装配
1)导入 jar 包(加入 Maven 依赖)
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
2)修改实验室(Lab)实体类
public class Lab {
@Resource(name="cheatSharm")
public Sharm sharm;
@Resource(name="nola")
public Nola nola;
public String admin;
……
}
3)对应的 Spring 配置文件
<bean id="nola" class="sharm.autowire.Nola"/>
<bean id="sharm" class="sharm.autowire.Sharm"/>
<bean id="cheatSharm" class="sharm.autowire.Sharm"/>
<bean id="lab" class="sharm.autowire.Lab">
<property name="admin" value="Luma"/>
</bean>
4)OK