持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
使用了 IOC/DI 以后,对象与对象之间的关系是通过配置文件 ref 属性组织在一起,而不再是通过硬编码的方式耦合在一起了。但这样做有弊端:就是需要额外编写大量的配置文件。
需要注意的是,自动装配只适用于对象类型的属性,即通过 ref 属性注入的 <Bean> 与 <Bean> 之间的关系,而不适用于简单类型,就是基本类型和 String 类型。
自动装配模式
使用基于 XML 的配置元数据时,可以使用 <bean /> 元素的 autowire 属性为 bean 定义指定 autowire 模式。autowiring 功能有四种模式,你可以为每个 bean 指定 autowiring,从而可以选择要 autowiring 的对象。以下表中介绍了四种装配模式:
| autowire 属性值 | 自动装配方式 |
|---|---|
| no | (默认)不使用自动装配。必须引用由 ref 属性来指定对象之间的依赖关系。大型项目中不建议设置为默认方式。 |
| byName | 根据属性名自动装配。如果某一个 <bean> 的 id 值,与当前 <bean> 的某一个属性名相同,则自动注入;如果没有找到,则什么也不做。(本质是寻找属性名的 set 方法) |
| byType | 根据属性类型自动装配。如果某一个 <bean> 的类型,恰好与当前 <bean> 的某一个属性的类型相同,则主动注入;如果有多个 <bean> 的类型都与当前 <bean> 的某一个属性的类型相同,则 Spring 将无法决定注入哪一个 <bean>,就会抛出一个异常;如果没有找到,则什么也不做。 |
| constructor | 根据构造器自动装配。与 byType 类似,区别是它需要使用构造方法。如果 Spring 没有找到与构造方法参数列表一致的 <bean>,则会抛出异常。 |
接下来我们把环境先搭建好,本实验中主要需要大家学会如何进行自动装配的配置。
搭建环境参考前面一个文章 关于Spring的小知识和第一个spring项目的创建 - 掘金 (juejin.cn)
然后我们在dao,resourcees里面添加对应Java和xml文件,最后在test里面书写测试方法
ADAO相关代码
BDAO相关代码
User代码
package com.yamiya.pojo;
import java.util.Date;
public class Users {
private Integer userid;
private String username;
private String usertype;
private Date hiredate;
/**
* 无参构造器
*/
public Users(){
}
/**
* 带参数构造器
* @param userid 用户编号
* @param username 用户名
* @param usertype 用户类型
*/
public Users(Integer userid, String username, String usertype){
this.userid = userid;
this.username = username;
this.usertype = usertype;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public Integer getUserid() {
return userid;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsertype(String usertype) {
this.usertype = usertype;
}
public String getUsertype() {
return usertype;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public Date getHiredate() {
return hiredate;
}
@Override
public String toString() {
return super.getClass().getName() + "[userid = " +userid+", username = "+username+", usertype = "+ usertype + "]";
}
}
UserService代码
package com.yamiya.service;
import com.yamiya.dao.IUserADAO;
import com.yamiya.dao.IUserBDAO;
import com.yamiya.pojo.Users;
public class UserService {
private IUserADAO userdaoa;
private IUserBDAO userdaob;
private Users user;
public UserService(){
}
public UserService(IUserADAO userdaoa, IUserBDAO userdaob, Users user) {
this.userdaoa = userdaoa;
this.userdaob = userdaob;
this.user = user;
}
public void getUsers(){
System.out.println(user);
userdaob.updateUser(user);
userdaoa.queryUsers();
}
public IUserADAO getUserdaoa() {
return userdaoa;
}
public void setUserdaoa(IUserADAO userdaoa) {
this.userdaoa = userdaoa;
}
public IUserBDAO getUserdaob() {
return userdaob;
}
public void setUserdaob(IUserBDAO userdaob) {
this.userdaob = userdaob;
}
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
}
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">
</beans>
到这里环境完成,下面开始装配
根据属性名自动装配
这种模式需要指定属性名的自动装配。需要在 Spring 容器中,也就是配置文件中对 bean 元素中的 autowire 属性设置为 byName。然后容器将 bean 的属性与配置文件中定义为相同名称的 bean 进行匹配和连接。如果找到匹配项,它将注入这些 bean,否则,它将抛出异常。
我们先来分析一下提供给大家的代码:
提供给大家两个接口 IUserADAO 和 IUserBDAO ,分别创建查询所有用户信息和更新用户信息的方法,在实现类 UserADAOImpl 和 UserBDAOImpl 中进行方法的实现,方法中的内容比较简单。
这个 UserService 类用来调用之前所说的接口中的方法,所以需要在该类中注入 2 个接口和 1 个数据 Bean 的实例,如果接口实例没有注入的话,那么在 getUsers() 方法里就无法调用接口中方法,还会抛出空指针异常。
以上所讲的这些代码需要清楚这些提供的类和接口是干什么用的。
接下来需要采用根据属性名自动装配模式,将接口 IUserADAO 和 IUserBDAO 以及类 Users 的对象实例注入到类 UserService 中。
1.修改springAutowireByName.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="user" class="com.yamiya.pojo.Users">
<property name="userid" value="2020606"/>
<property name="username" value="King" />
<property name="usertype" value="VVVip会员" />
</bean>
<bean id="userdaoa" class="com.yamiya.dao.UserADAOImpl"></bean>
<bean id="userdaob" class="com.yamiya.dao.UserBDAOImpl"></bean>
<bean id="userservice" class="com.yamiya.service.UserService" autowire="byName" />
</beans>
主要使用的是 <bean> 元素中的属性 autowire,采用的是 autowire="byName",通过名字进行自动注入操作。
需要注意:id 的属性值必须和 UserService 类中的属性名保持一致,否则无法通过名字进行查找匹配。
2. 修改测试类 TestAutowire 添加 testAutowireByName() 测试方法进行测试:
package com.yamiya;
import com.yamiya.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAutowire {
@Test
public void testAutowireByName(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springAutowireByName.xml");
UserService us = context.getBean("userservice", UserService.class);
us.getUser();
context.close();
}
}
根据属性类型自动装配
这种模式需要根据属性类型自动装配。需要在 Spring 容器中,也就是配置文件中对 bean 元素中的 autowire 属性设置为 byType。然后容器将 bean 的类型与配置文件中定义的 bean 的类型进行匹配和连接。如果找到匹配项,它将注入这些 bean,否则,它将抛出异常。
同样我们接下来需要采用根据属性类型自动装配模式,将接口 IUserADAO 和 IUserBDAO 以及类 Users 的对象实例注入到类 UserService 中。
- 修改
springAutowireByType.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 class="com.yamiya.pojo.Users">
<property name="userid" value="2000125"/>
<property name="username" value="Demi" />
<property name="usertype" value="超级会员" />
</bean>
<bean class="com.yamiya.dao.UserADAOImpl"></bean>
<bean class="com.yamiya.dao.UserBDAOImpl"></bean>
<bean id="userservice" class="com.yamiya.service.UserService" autowire="byType" />
</beans>
主要使用的是 <bean> 元素中的属性 autowire,采用的是 autowire="byType",通过对象类型进行自动注入操作。
需要注意:配置的 bean 中 id 属性可以省略,但配置文件中提供的 bean 的类型必须和 UserService 类中的属性类型保持一致,否则无法通过类型进行查找匹配。
- 修改测试类
TestAutowire添加testAutowireByType()测试方法进行测试:
@Test
public void testAutowireByType(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springAutowireByType.xml");
UserService us = context.getBean("userservice", UserService.class);
us.getUsers();
context.close();
}
根据构造器自动装配
这种模式与 byType 非常相似,但它应用于构造器参数。Spring 容器中 bean 的 autowire 属性设置为 constructor。然后,它尝试把它的构造函数的参数与配置文件中 bean 的类型进行匹配和连接。如果找到匹配,它会注入这些 bean,否则它会抛出异常。
我们接下来需要采用根据构造器自动装配模式,将接口 IUserADAO 和 IUserBDAO 以及类 Users 的对象实例通过 UserService 类中的构造器进行注入。
- 修改
springAutowireConstructor.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 class="com.yamiya.pojo.Users">
<property name="userid" value="2000128"/>
<property name="username" value="Tina" />
<property name="usertype" value="普通会员" />
</bean>
<bean class="com.yamiya.dao.UserADAOImpl"></bean>
<bean class="com.yamiya.dao.UserBDAOImpl"></bean>
<bean id="userservice" class="com.yamiya.service.UserService" autowire="constructor" />
</beans>
主要使用的是 <bean> 元素中的属性 autowire,采用的是 autowire="constructor",通过对象类型进行自动注入操作。
需要注意:配置的 bean 中 id 属性可以省略,但是在 UserService 类中必须存在带参数的构造器,构造器参数类型还需要和配置文件中的 bean 的类型一致。
- 修改测试类
TestAutowire添加testAutowireConstructor()测试方法进行测试:
@Test
public void testAutowireConstructor(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springAutowireConstructor.xml");
UserService us = context.getBean("userservice", UserService.class);
us.getUsers();
context.close();
}
到这里,三种方法已经完成,大家可以去试试哦
总结
这篇讲述了 Bean 自动装配的 3 种模式,一般主要使用的前 2 种 byName 和 byType 。
自动装配的优点:
- 自动装配可以显著减少指定属性或构造器参数。
- 自动装配可以随着对象的发展更新配置,在开发期间尤其有用,也不需要在代码库变得更稳定时切换到显示装配。
自动装配的局限性和缺点:
property和constructor-arg设置中的显式依赖项始终会覆盖自动装配。- 自动装配不如显式装配精确。