已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
当前回答
针对5岁儿童的依赖注入。
当你自己去把冰箱里的东西拿出来时,你可能会引起问题。你可能会让门开着,你可能会得到妈妈或爸爸不希望你拥有的东西。你甚至可能在寻找我们甚至没有或已经过期的东西。
你应该做的是陈述一个需要,“我需要午餐时喝点东西”,然后我们会确保你坐下吃饭时有东西。
其他回答
依赖注入是一种实践,其中对象的设计方式是从其他代码段接收对象实例,而不是在内部构造它们。这意味着可以在不更改代码的情况下替换实现对象所需接口的任何对象,这简化了测试,并改进了去耦。
例如,考虑这些类:
public class PersonService {
public void addManager( Person employee, Person newManager ) { ... }
public void removeManager( Person employee, Person oldManager ) { ... }
public Group getGroupByManager( Person manager ) { ... }
}
public class GroupMembershipService() {
public void addPersonToGroup( Person person, Group group ) { ... }
public void removePersonFromGroup( Person person, Group group ) { ... }
}
在本例中,PersonService::addManager和PersonService::removeManager的实现需要GroupMembershipService的实例才能完成其工作。如果没有依赖注入,传统的方法是在PersonService的构造函数中实例化一个新的GroupMembershipService,并在两个函数中使用该实例属性。但是,如果GroupMembershipService的构造函数有多个它需要的东西,或者更糟的是,需要在GroupMembershipServices上调用一些初始化“setter”,代码增长相当快,PersonService现在不仅依赖于GroupMembershipService,还依赖于GroupMembershipService所依赖的所有其他东西。此外,与GroupMembershipService的链接被硬编码到PersonService中,这意味着您不能为了测试目的而“虚拟”GroupMembershipServices,或者在应用程序的不同部分使用策略模式。
使用依赖注入,而不是在PersonService中实例化GroupMembershipService,您可以将其传递给PersonService构造函数,或者添加Property(getter和setter)来设置其本地实例,并与他们合作。这也意味着,任何属于GroupMembershipService的子类或实现GroupMembershipServices接口的内容都可以“注入”到PersonService中,PersonService不需要知道更改。
摘自《扎实的Java开发人员:Java 7和多语言编程的关键技术》一书
DI是IoC的一种特殊形式,因此查找依赖项的过程是不受当前执行代码的直接控制。
让我们想象一下,你想去钓鱼:
没有依赖注入,你需要自己处理所有的事情。你需要找一艘船,买一根鱼竿,寻找诱饵等等。当然,这是可能的,但这给你带来了很多责任。在软件方面,这意味着你必须对所有这些东西进行查找。通过依赖注入,其他人负责所有准备工作,并为您提供所需的设备。你将收到(“被注射”)船、鱼竿和鱼饵——所有这些都准备好使用。
这是我见过的关于依赖注入和依赖注入容器的最简单的解释:
无依赖注入
应用程序需要Foo(例如控制器),因此:应用程序创建Foo应用程序调用FooFoo需要Bar(例如服务),因此:Foo创建BarFoo调用Bar酒吧需要Bim(服务、存储库,…),因此:条形图创建Bim酒吧有点事
使用依赖注入
应用程序需要Foo,需要Bar,需要Bim,因此:应用程序创建Bim应用程序创建Bar并赋予它Bim应用程序创建Foo并给它Bar应用程序调用FooFoo调用Bar酒吧有点事
使用依赖注入容器
应用程序需要Foo,因此:应用程序从容器中获取Foo,因此:容器创建Bim容器创建Bar并赋予它Bim容器创建Foo并给它Bar应用程序调用FooFoo调用Bar酒吧有点事
依赖注入和依赖注入容器是不同的:
依赖注入是一种编写更好代码的方法DI容器是帮助注入依赖项的工具
您不需要容器来执行依赖注入。然而,容器可以帮助您。
我知道已经有很多答案,但我发现这非常有用:http://tutorials.jenkov.com/dependency-injection/index.html
无相关性:
public class MyDao {
protected DataSource dataSource = new DataSourceImpl(
"driver", "url", "user", "password");
//data access methods...
public Person readPerson(int primaryKey) {...}
}
附属国:
public class MyDao {
protected DataSource dataSource = null;
public MyDao(String driver, String url, String user, String password) {
this.dataSource = new DataSourceImpl(driver, url, user, password);
}
//data access methods...
public Person readPerson(int primaryKey) {...}
}
注意DataSourceImpl实例化是如何移动到构造函数中的。构造函数接受四个参数,即DataSourceImpl所需的四个值。虽然MyDao类仍然依赖于这四个值,但它本身不再满足这些依赖关系。它们由创建MyDao实例的任何类提供。