您的位置:首页 > 编程语言 > Java开发

Spring Ioc、依赖注入原理

2017-01-06 15:10 190 查看
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  

<beans>  

 <bean id="B" class="*****.BImpl"> 实体类名包  

 <bean id ="A"  class="****.A">  

    <proproty name="obj">  

    <ref bean ="B"  

    </property>     

 </bean>  

</beans>  

这里的配置文件将BImpl实现类和A类加入,并将BImpl作为A类的一个参数。  

 容器加载通过xml来实例化相关的bean。

通过上面不难发现:  

(1) A类是通过接口B类来接受BImpl实例,所以  

当我们又有新的 B类的实现是,只需要修改xml文件即可。

通过上例可以总结得出:

1.依赖类是通过Spring容器解析xml后来注入的,而不是使用它的类(A)来自己制造,这就是依赖的注入。

2.A类对BImpl类的依赖转移到对B接口的依赖,控制权由类转移到了接口,即由"实现"转移到"抽象"中。

3.通过将对实例的依赖,改为对接口的依赖。是面向接口编程的一个要义。也是程序解耦的一个措施。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: