目录
一、自动装配简介
自动装配是 Spring 框架提供的一种依赖注入方式,它可以根据指定的策略,在 IOC 容器中自动匹配某个 Bean,并为目标 Bean 中的依赖属性赋值。通过自动装配,开发者无需手动配置每个 Bean 的依赖关系,Spring 会自动完成这些工作。
Spring 支持以下几种自动装配模式(分为三讲):
-
byType:根据属性类型自动装配。
-
byName:根据属性名称自动装配。
-
constructor:根据构造函数参数类型自动装配。
-
no:默认模式,不启用自动装配。
在本示例中,我们通过 XML 配置文件手动配置了 Bean 的依赖关系,但自动装配的核心思想是让 Spring 自动完成这些工作。
二、项目结构与场景模拟
1. 项目结构
spring_joc_xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── atguigu
│ │ │ └── spring
│ │ │ ├── controller
│ │ │ │ └── UserController.java # 用户控制器
│ │ │ ├── dao
│ │ │ │ ├── impl
│ │ │ │ │ └── UserDaoImpl.java # 用户数据访问对象实现类
│ │ │ │ └── UserDao.java # 用户数据访问对象接口
│ │ │ ├── service
│ │ │ │ ├── impl
│ │ │ │ │ └── UserServiceImpl.java # 用户服务实现类
│ │ │ │ └── UserService.java # 用户服务接口
│ │ └── resources
│ │ └── spring-autowire-xml.xml # Spring 自动装配配置文件
│ └── test
│ └── java
│ └── com
│ └── atguigu
│ └── spring
│ └── test
│ └── AutowireByXMLTest.java # 测试自动装配功能
└── pom.xml
2. 场景模拟
我们模拟了一个简单的用户管理模块,包含以下组件:
-
UserController:用户控制器,负责处理用户相关的请求。
-
UserService:用户服务接口,定义用户相关的业务方法。
-
UserServiceImpl:用户服务实现类,实现具体的业务逻辑。
-
UserDao:用户数据访问对象接口,定义数据库操作方法。
-
UserDaoImpl:用户数据访问对象实现类,实现具体的数据库操作。
代码实现:
UserController.java
package com.atguigu.spring.controller;
import com.atguigu.spring.service.UserService;
public class UserController {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public void saveUser() {
userService.saveUser();
}
}
UserService.java
package com.atguigu.spring.service;
public interface UserService {
void saveUser();
}
UserServiceImpl.java
package com.atguigu.spring.service.impl;
import com.atguigu.spring.dao.UserDao;
import com.atguigu.spring.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void saveUser() {
userDao.saveUser();
}
}
UserDao.java
package com.atguigu.spring.dao;
public interface UserDao {
void saveUser();
}
UserDaoImpl.java
package com.atguigu.spring.dao.impl;
import com.atguigu.spring.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void saveUser() {
System.out.println("保存成功");
}
}
三、配置 Bean
在 spring-autowire-xml.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置 UserController,注入 UserService -->
<bean id="userController" class="com.atguigu.spring.controller.UserController">
<property name="userService" ref="userService"></property>
</bean>
<!-- 配置 UserServiceImpl,注入 UserDao -->
<bean id="userService" class="com.atguigu.spring.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 配置 UserDaoImpl -->
<bean id="userDao" class="com.atguigu.spring.dao.impl.UserDaoImpl"></bean>
</beans>
配置解析:
-
userController:配置了
UserController
,并通过<property>
标签将userService
注入到UserController
中。 -
userService:配置了
UserServiceImpl
,并通过<property>
标签将userDao
注入到UserServiceImpl
中。 -
userDao:配置了
UserDaoImpl
,作为数据访问层的实现。
四、测试自动装配
AutowireByXMLTest.java
package com.atguigu.spring.test;
import com.atguigu.spring.controller.UserController;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AutowireByXMLTest {
@Test
public void testAutowire() {
// 加载 Spring 配置文件
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
// 获取 UserController 实例
UserController userController = ioc.getBean(UserController.class);
// 调用 saveUser 方法
userController.saveUser();
}
}
测试解析:
-
加载配置文件:通过
ClassPathXmlApplicationContext
加载spring-autowire-xml.xml
配置文件,初始化 Spring IOC 容器。 -
获取 Bean:从容器中获取
UserController
实例。 -
调用方法:调用
userController.saveUser()
方法,触发业务逻辑。
五、输出结果
保存成功
输出解析:
-
UserController
调用userService.saveUser()
方法。 -
UserServiceImpl
调用userDao.saveUser()
方法。 -
UserDaoImpl
执行System.out.println("保存成功")
,输出结果。
六、测试思路与总结
1、初始化 Spring 容器
使用 ClassPathXmlApplicationContext 加载 spring-autowire-xml.xml 配置文件,初始化 Spring IOC 容器。这一步的目的是让 Spring 根据配置文件创建并管理所有的 Bean。
2、获取 Bean 实例
通过 ioc.getBean(UserController.class) 从容器中获取 UserController 的实例。这一步的目的是验证 Spring 是否能够正确地创建 UserController 实例,并注入其依赖的 UserService。
3、调用方法并验证结果
调用 userController.saveUser() 方法,触发整个调用链:
UserController 调用 UserServiceImpl 的 saveUser() 方法。
UserServiceImpl 调用 UserDaoImpl 的 saveUser() 方法。
最终,UserDaoImpl 的 saveUser() 方法会输出 "保存成功"。通过观察控制台输出,验证结果是否符合预期。
4、异常情况考虑
如果 Spring 容器初始化失败(例如配置文件路径错误),测试会抛出异常。如果依赖注入失败(例如 Bean 未正确配置),调用 saveUser() 方法时会抛出 NullPointerException。如果 UserDaoImpl 的 saveUser() 方法未正确实现,输出结果会与预期不符。