spring框架通过依赖注入,对象之间的依赖关系由 Spring 容器来管理,而不是在代码中硬编码。
这意味着一个类不再需要自己创建和管理其依赖的对象,而是由 Spring 容器将依赖的对象注入到类中。
例如:
在一个用户管理系统中,UserService 类依赖于 UserDao 类,使用 Spring 的依赖注入,UserService 类不需要在内部使用 new 关键字创建 UserDao 的实例,而是由 Spring 容器将 UserDao 的实例注入到 UserService 中。这样,UserService 与 UserDao 的实现细节解耦,当 UserDao 的实现发生变化时,UserService 类不需要进行修改。
场景一:更换 UserDao 的实现类
原理
Spring 的自动注入基于依赖倒置原则,让 UserService 依赖于抽象(接口)而非具体实现。当需要更换 UserDao 实现类时,只需在 Spring 的配置中调整注入的具体实现类,而 UserService 类本身依赖的是抽象接口,不会受到实现类更换的影响。
代码示例
1. 定义 UserDao 接口
// UserDao 接口,定义用户数据访问的方法
public interface UserDao {
void saveUser();
}
2. 实现 UserDao 接口
// 旧的 UserDao 实现类
import org.springframework.stereotype.Repository;
@Repository
public class OldUserDao implements UserDao {
@Override
public void saveUser() {
System.out.println("使用旧方法保存用户信息");
}
}
// 新的 UserDao 实现类
import org.springframework.stereotype.Repository;
@Repository
public class NewUserDao implements UserDao {
@Override
public void saveUser() {
System.out.println("使用新方法保存用户信息");
}
}
3. 定义 UserService 类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private UserDao userDao;
@Autowired
public UserService(UserDao userDao) {
this.userDao = userDao;
}
public void createUser() {
userDao.saveUser();
}
}
在 UserService 类中,构造函数通过 @Autowired 注解注入 UserDao 接口的实现类。UserService 只依赖于 UserDao 接口,不关心具体是哪个实现类。
4. Spring 配置类(使用 Java 配置)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
// 这里可以选择注入旧的实现类
// @Bean
// public UserDao userDao() {
// return new OldUserDao();
// }
// 也可以选择注入新的实现类
@Bean
public UserDao userDao() {
return new NewUserDao();
}
@Bean
public UserService userService(UserDao userDao) {
return new UserService(userDao);
}
}
场景二:UserDao 构造函数发生变化
代码示例
首先,我们有一个简单的 UserDao 类和 UserService 类,UserService 类手动创建 UserDao 实例。
// UserDao 类,用于处理用户数据访问
class UserDao {
public UserDao() {
System.out.println("UserDao 实例被创建");
}
public void saveUser() {
System.out.println("保存用户信息");
}
}
// UserService 类,用于处理用户业务逻辑,依赖于 UserDao
class UserService {
private UserDao userDao;
public UserService() {
this.userDao = new UserDao();
}
public void createUser() {
userDao.saveUser();
}
}
// 测试类
public class Main {
public static void main(String[] args) {
UserService userService = new UserService();
userService.createUser();
}
}
在这个初始代码中,UserService 类的构造函数里手动使用 new 关键字创建了 UserDao 实例。
构造函数变化
现在,假设 UserDao 的需求发生了变化,需要在构造函数中传入一个数据库连接字符串。
// 修改后的 UserDao 类,构造函数需要传入数据库连接字符串
class UserDao {
private String dbConnectionString;
public UserDao(String dbConnectionString) {
this.dbConnectionString = dbConnectionString;
System.out.println("UserDao 实例被创建,使用数据库连接字符串: " + dbConnectionString);
}
public void saveUser() {
System.out.println("使用 " + dbConnectionString + " 保存用户信息");
}
}
// UserService 类,由于 UserDao 构造函数变化,需要修改
class UserService {
private UserDao userDao;
public UserService() {
// 这里需要修改,因为 UserDao 构造函数发生了变化
this.userDao = new UserDao("jdbc:mysql://localhost:3306/mydb");
}
public void createUser() {
userDao.saveUser();
}
}
// 测试类
public class Main {
public static void main(String[] args) {
UserService userService = new UserService();
userService.createUser();
}
}
可以看到,由于 UserDao 的构造函数发生了变化,UserService 类的构造函数也必须进行修改,这就体现了 UserService 与 UserDao 实现细节的紧密耦合。
2861

被折叠的 条评论
为什么被折叠?



