这是一个奇怪的例子,但第一个演示了依赖注入容器会做什么,第二个演示了一个对象将参数传递给另一个对象。第一个将其依赖项嵌入为调用类的实例变量;第二个是程序性质的。就其本身而言,两者都没有错。这取决于您的依赖项有多复杂以及您希望如何管理代码。
仅查看您提供的注入器代码,您并不清楚为什么要使用依赖注入。但是暂时考虑一个更复杂(也更典型)的例子。
客户服务:
public class CustomerService implements ICustomerService {
private IOrderDAO orderDao;
public void setOrderDAO(IOrderDAO orderDao) {
this.orderDao = orderDao;
}
public Order getOrderByDate(Integer customerId, Date date) {
return this.orderDao.findOrderByDate(customerId, date);
}
}
OrderDAO(默认实现):
public OrderDAO implements IOrderDAO {
private javax.sql.DataSource dataSource;
public void setDataSource(javax.sql.DataSource dataSource) {
this.dataSource = dataSource;
}
public Order findOrderByDate(Integer customerId, Date date) {
...
}
}
StubOrderDAO(存根实现):
public StubOrderDAO implements IOrderDAO {
public Order findOrderByDate(Integer customerId, Date date) {
return new HardCodedOrder(); // this class would extend or implement Order
}
}
在运行时,实例CustomerService
不会知道正在使用哪个 IOrderDAO 实现。这意味着您可以非常轻松地,例如,通过初始化 CustomerService 来引导一个单元测试StubOrderDAO
(它总是返回一个硬编码的客户)。同样,您的 DataSource 实现可能会有所不同(模拟数据源或在不同运行时环境中不同的数据源)。
因此,用于生产用途的注射器可能如下所示:
// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new OrderDAO();
javax.sql.dataSource dataSource = jndiContext.lookup("java:comp/env/MyDataSource");
// initialize
dao.setDataSource(dataSource);
service.setOrderDAO(dao);
return service;
而使用本地(测试)数据源的注入器可能如下所示:
// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new OrderDAO();
javax.sql.dataSource dataSource = new DriverManagerDataSource("jdbc:sqlserver:yadayada...", "myUsername", "myPassword");
// initialize
dao.setDataSource(dataSource);
service.setOrderDAO(dao);
return service;
集成测试的注入器可能如下所示:
// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new StubOrderDAO();
// initialize
service.setOrderDAO(dao);
return service;
所以它本质上是一种实现良好分层和关注点分离的方法,即您访问数据库的方式独立于您访问数据以创建域模型的方式,并且两者都独立于您所做的任何聚合或业务逻辑处理in CustomerService
(为简洁起见,此处未显示)。
这更有意义吗?