关于控制反转和依赖注入的文章和书籍不少,对其定义也解释的也仁者见仁,这里就不赘述了,这是本人(只表明我的观点)理解以后用通俗的例子和平淡的话词为您解释,但愿对您有所帮助:spring
控制反转(IoC/Inverse Of Control): 调用者再也不建立被调用者的实例,由spring框架实现(容器建立)因此称为控制反转。框架
依赖注入(DI/Dependence injection) : 容器建立好实例后再注入调用者称为依赖注入。测试
当 某个角色(多是一个Java实例,调用者)须要另外一个角色(另外一个Java实例,被调用者)的协助时,在传统的程序设计过程当中,一般由调用者来建立被调 用者的实例,。若是建立被调用者实例的工做再也不由调用者来完成,而是由外部容器完成,所以称为控制反转; 建立被调用者 实例的工做一般由外部容器来完 成,而后注入调用者,所以也称为依赖注入。this
下面一个小实例:spa
定义一个接口 设计
public interface Person { void sayHello(); }
第一个实现类:code
public class Chinese implements Person { public void sayHello() { System.out.println("您好 !"); } }
第二个实现类: 对象
public class American implements Person { public void sayHello() { System.out.println("How do you do ."); } }
注意这个类与传统设计有什么区别:该类调用Person子类的方法,传统设计在本类中创造实例,而在此类里并无创造实例blog
public class User { Person p; public Person getP() { return p; } //使用setter注入 public void setP(Person p) { this.p = p; } //调用person子类重写的sayHello方法,这里的p并无实例化 public void function(){ p.sayHello(); } }
外部‘容器’接口
public class Container{ public static User getBean(){ Person p=new Chinese(); User user = new User(); //由容器‘注入’实例 user.setP(p); return user; } }
测试类:
public class Test{ public static void main(String[] args){ User user = Container.getBean(); user.function(); } }
//后台输出‘您好’
经过这个例子应该看懂了控制反转,和依赖注入了吧,这个是否是与传统设计相‘反了’。:-D
相关知识
依赖和耦合(Dependency and Coupling)
若是模块A调用模块B提供的方法,或访问模块B中的某些数据成员(固然,在面向对象开发中通常不提倡这样作),咱们就认为模块A依赖于模块B,模块A和模块B之间发生了耦合。
那么,依赖对于咱们来讲到底是好事仍是坏事呢?
因为人类的理解力有限,大多数人难以理解和把握过于复杂的系统。把软件系统划分红多个模块,能够有效控制模块的复杂度,使每一个模块都易于理解和维护。但 在这种状况下,模块之间就必须以某种方式交换信息,也就是必然要发生某种耦合关系。若是某个模块和其它模块没有任何关联(哪怕只是潜在的或隐含的依赖关 系),咱们就几乎能够判定,该模块不属于此软件系统,应该从系统中剔除。若是全部模块之间都没有任何耦合关系,其结果必然是:整个软件不过是多个互不相干 的系统的简单堆积,对每一个系统而言,全部功能仍是要在一个模块中实现,这等于没有作任何模块的分解。
所以,模块之间一定会有这样或那样的依赖关系,永远不要幻想消除全部依赖。可是,过强的耦合关系(如一个模块的变化会形成一个或多个其余模块也同时发生 变化的依赖关系)会对软件系统的质量形成很大的危害。特别是当需求发生变化时,代码的维护成本将很是高。因此,咱们必须想尽办法来控制和消解没必要要的耦 合,特别是那种会致使其它模块发生不可控变化的依赖关系。依赖倒置、控制反转、依赖注入等原则就是人们在和依赖关系进行坚苦卓绝的斗争过程当中不断产生和发 展起来的。