在传统的编程中,对象通常自己负责创建和管理它的依赖项。例如:
public class UserService {
private UserRepository userRepository = new JdbcUserRepository(); // 直接创建依赖
public void addUser(String username) {
userRepository.save(username);
}
}
在这种模式下,UserService
直接依赖于JdbcUserRepository
的具体实现,导致代码耦合性高,难以替换或测试。
而在依赖注入模式下,依赖关系由外部容器(如Spring容器)提供,而不是由对象自身创建。例如:
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) { // 通过构造函数注入依赖
this.userRepository = userRepository;
}
public void addUser(String username) {
userRepository.save(username);
}
}
在这里,UserService
不再关心UserRepository
的具体实现,而是通过构造函数接收一个UserRepository
实例。Spring容器会自动将合适的实现(如JdbcUserRepository
或MongoUserRepository
)注入到UserService
中。
Spring支持以下三种常见的依赖注入方式:
通过构造函数传递依赖项。这是推荐的方式,尤其是对于强制依赖项。
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
final
修饰符)。通过Setter方法设置依赖项。适用于可选依赖项。
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
null
,需要额外的检查。通过注解直接注入依赖项。这是最简洁的方式,但不推荐作为主要注入方式。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
final
修饰符,可能导致依赖项为null
。Spring容器(如ApplicationContext
)负责管理Bean的生命周期和依赖注入。以下是其工作流程:
@Component
、@Service
等),发现并注册所有Bean。// 数据访问接口
public interface UserRepository {
void save(String username);
}
// JDBC实现
@Repository
public class JdbcUserRepository implements UserRepository {
@Override
public void save(String username) {
System.out.println("Saving user '" + username + "' to relational database via JDBC.");
}
}
// MongoDB实现
@Repository
public class MongoUserRepository implements UserRepository {
@Override
public void save(String username) {
System.out.println("Saving user '" + username + "' to MongoDB.");
}
}
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void addUser(String username) {
userRepository.save(username);
}
}
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
}
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);
userService.addUser("Alice");
}
}