Spring Ioc、依赖注入原理
Sping 框架的核心就是IOC控制反转和DI依赖注入,并通过这两方面实现松耦合。
IOC控制反转:其实这个Sping构架核心的概念没有这么复杂,更不想书上描述的那样晦涩。Java 程序员都知道:Java程序的每一个业务逻辑至少要两个以上的对象来协作完成。通常每个对象在使用它合作的对象时,自己均要使用像new object()这样的语法
来完成合作对象的申请工作。这个时候你就会发现对象之间的 耦合度 高了。
(耦合度:是指对模块之间的关联程度的度量。耦合度的强弱取决于模块接口之 间的复杂性、调用模块之间的方式以及通过界面传送的多少。模块之间的耦合度 是指模块之间的:依赖关系、控制关系、调用关系、数据传递关系。模块之间连 系越多,其耦合性越高,同时表名其独立关系越差。)
而IOC的思想是:用Spring容器来实现这些相互的依赖的对象的创建、协调工作。
对象只需要关系业务逻辑本身就可以了。从这方面来说,对象如何得到它的协作对象的责任就被反转了(IOC)。
IOC与ID:
首选先来说说IOC(Inversion of Control,控制倒转)。这个是Spring框架的核心,贯穿始终。所谓的IOC对于Spring框架来说,就是由Spring框架负责控制对象的生命周期和对象之间的关系。举个例子比如:我们是如何找女朋友的呢?常见的是看见长的漂亮的妹子对她有想法,然后打听妹子们的兴趣爱好想办法搞到:QQ号、电话号、微信号等等。然后想尽办法认识她打好关系,投其所好,送其所要。最后就………..嘿嘿嘿,这个过程必定是复杂的深奥的我们必须自己设计和面对每一个环节。传统的程序开发也是如此,在一个对象中如果要使用另外的对象就必须要得到它(自己new一个,或者是从JNDI中查询一个),然后使用完了还要将对象销毁(比如:connection关闭连接释放资源等),这样对象始终会和其他对象的接口或者类耦合起来。
那么IOC是如何做到的呢?举个例子比如:连接上面个例子,接着说。IOC的做法就有点好像通过婚姻介绍所一样。我像婚介提出一个请求,告诉他我要找什么样子的女朋友,比如说像刘亦菲,身材像柳岩,唱歌像张靓颖等等。然后婚介就会按照我们的要求,提供一个妹子,我们只需要和他约会、交往看双方是否相互有意,简单明了。如果婚介提供的妹子不符合我们的要求,我们就会抛出异常表示不满意。整个过程已经不再又我自己控制了,而是有婚介这样一个类似容器的机构来控制。Spring框架所倡导的开发模式也是如此,所有的类多会在Spring容器中登记告诉Spring你是个什么东西,你需要什么东西。然后Spring会在系统运行到适当的时候,把你要的主动给你,同时也把你交给其他需要你的对象。所有类的创建和销毁多由Spring来控制。就是说控制对象的生命周期的不在是引用它的对象了,而是Spring容器。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象多被Spring控制,所有这就叫控制反转IOC。
IOC另一个重点是在系统运行中,动态的像某个对象提供它所需要的对象。这一点就是通过DI(Dependency Injection,依赖注入)来实现的。比如:对象A需要操作数据库,以前我们总是在A对象中自己编写代码来获得一个Connection对象,有了Spring我们只需告诉Spring 对象A中需要一个connection,至于connection是怎么构造,何时构造出来的,对象A就不需要知道了。在系统运行时,Spring会在适当的时候制造一个Connection,然后想打针一样注射到对象A当中。这样就完成了个个的对象之间的关系控制。对象A需要依赖Connection才能正常运行,而这个Connection是由Spring注入到对象A当中,依赖注入的名称就是这样来的。那么DI控制反转是怎么实现的呢?在Java当中有个重要的特征就是发射(reflection),它允许程序运行时动态的生成对象、执行对象的方法、改变对象的属性。而Spring就是通过发射来实现注入的。
如果你还不理解我在说的简单明了些。
1.使用Ioc,对象是变动的接受依赖类,而不是主动去找。Spring容器在实例化的时候主动将它的依赖类注入给它,也可以这样理解:控制反转将类的主动权转移到接口上,依赖注入通过.xml配置文件在实例化时将其依赖注入。
2.例如:比如a类依赖于b类,那么a类之中就有b类的引用(在说简单点就是拥有b类这么一个属性),也就是说a类要想执行一个完整的功能必须要建立一个前提,在a类中实例化b类的一个属性,拥有b类的一切功能,接下来就是依赖注入了。就像前面说的a类想完成一个完整的功能必须要为自己的b类属性实例化,而在MVC设计模式中,这种现象很常见,为了简化这种实例化的工作,Spring容器就产生了。它可以统一管理这种实例化频繁的操作,就是说这种本来由自己实例化的工作交给了Spring容器去控制,这就是控制反转了。实现的案例代码可以看一下代码。
- //**定义接口B类
- public interface B{
- void doMethod();
- }
- //实现接口B类
- public class BImpl implements B{
- //以及实现doMethod()方法
- public void doMethod(){……}
- }
- //类A
- public class A{
- B obj;
- public A(){}
- public void doSth(){
- …
- obj.doMethod();
- }
- public void setObj(B b){
- this.obj = d;
- }
- }
- 代码中可以看出:
- (1) A类的变量obj可以接受任何B类的实例
- (2) BImpl实现类的实例不是通过A类自己new出来,而是通过setter来由外部传给它。
- 此时考虑 A类依赖的实例如何从外部注入,就要通过xml定义,Spring容器再依据xml来实例化。
- 创建一个spring-context.xml
实体类名包 - <ref bean =”B”
- 这里的配置文件将BImpl实现类和A类加入,并将BImpl作为A类的一个参数。
- 容器加载通过xml来实例化相关的bean。
- 通过上面不难发现:
- (1) A类是通过接口B类来接受BImpl实例,所以
- 当我们又有新的 B类的实现是,只需要修改xml文件即可。
- 通过上例可以总结得出:
1.依赖类是通过Spring容器解析xml后来注入的,而不是使用它的类(A)来自己制造,这就是依赖的注入。
2.A类对BImpl类的依赖转移到对B接口的依赖,控制权由类转移到了接口,即由"实现"转移到"抽象"中。
3.通过将对实例的依赖,改为对接口的依赖。是面向接口编程的一个要义。也是程序解耦的一个措施。
还没有评论,来说两句吧...