Sping 框架的核心就是IOC控制反转和DI依赖注入,并通过这两方面实现松耦合。 (1) 使用Ioc,对象是被动的接受依赖类,而不是自己主动去找。容器在实例化的时候主动将它的依赖类注入给它。 亦可以这样理解:控制反转将类的主动权转移到借口上,依赖注入通过xml配置文件在类实例化是将其依赖注入。 (2) 从UML查看java对象之间的关系即是依赖。 例如:比如a对象依赖于b对象,那么a类中就会有b类的引用(简单理解就是拥有b类的这么一个属性),也就是说a对象要想执行一个完整的功能, 必须建立一个前提——a对象中的b类属性已经实例话,并且拥有b类的一切功能;现在可以去了解什么是依赖注入了,就像前面说过的,a对象想完 成一个完整的功能,要先为自己的b类属性实例化,而在MVC模式中,这种现象很常见,为了简化这种实例化的工作,spring容器就产生了,它可以 统一管理这种实例化频繁的操作,就是说这种本来应由自己实例化的工作交给Spring容器去控制了,也就是说控制反转了,实现的方案之一是在上 述a类中提供一个关于b类的setter方法,这个方法会被Spring容器控制。
(3) 从代码角度看实例: 假设有一个需求,类Business需要调用类DependencyClass的方法doMethod(), 按照日常的做法,得到如下代码示例: //*类DependencyClass publi class Dependency{ public void doMethod(){}; } //**类Business public class Business{ DependencyClass obj; public Business(){ obj = new DependencyClass(); } public void doSth(){ obj.doMethod(); } }
先将Business里的DependencyClass实例的获得改为setter方式, 其次,将DependencyClass 类改为某个接口的实现,故有如下代码: //**接口IDependency public interface IDependency{ void doMethod(); } //**类Dependency public class DependencyClass implements IDpendency{ public void doMethod(){......} } //类Business public class Business{ Idependency obj; public Business(){} public void doSth(){ ... obj.doMethod(); } public void setObj(Idependency d){ this.obj = d; } } 代码中可以看出: (1) Business的变量obj可以接受任何IDenpendency的实例 (2) DependencyClass 的实例不是通过Business自己new出来,而是通过setter来由外部传给它。 此时考虑Business依赖的实例如何从外部注入,就要通过xml定义,spring容器再依据xml来实例化。 创建一个spring-context.xml <beans> <bean id="dependency" class="*****.DependencyClass"> 实体类名包 <bean id ="business" class="****.Business"> <proproty name="obj"> <ref bean ="dependency" </property> </bean> </beans> 这里的配置文件将DependencyClass类和Business类加入,并将DependencyClass作为Business的一个 参数。 容器加载通过xml来实例化相关的bean. 通过上面不难发现: (1) Business 是通过接口IDependency来接受DependencyClass实例,所以 当我们又有新的IDenpendency的实现是,只需要修改xml文件即可,
通过上例可以总结出: a. 依赖类是通过spring容器解析xml后来注入的,而不是使用它的类(Business)来自己制造,这就是依赖的注入。 b. Bussiness 对类Dependency 的依赖转移到对接口IDependency的依赖,控制权由类转移到了接口,即由"实现"转移到"抽象"中。 c. 通过将对实例的依赖,改为对接口的依赖。是面向接口编程的一个要义。也是程序解耦的一个措施。