Spring Ioc、依赖注入原理 素颜马尾好姑娘i 2022-07-13 10:56 217阅读 0赞 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容器去控制,这就是控制反转了。实现的案例代码可以看一下代码。 1. //\*\*定义接口B类 2. **public** **interface** B\{ 3. **void** doMethod(); 4. \} 5. 6. //实现接口B类 7. **public** **class** BImpl **implements** B\{ 8. //以及实现doMethod()方法 9. **public** **void** doMethod()\{......\} 10. \} 11. //类A 12. **public** **class** A\{ 13. B obj; 14. **public** A()\{\} 15. **public** **void** doSth()\{ 16. ... 17. obj.doMethod(); 18. \} 19. **public** **void** setObj(B b)\{ 20. **this**.obj = d; 21. \} 22. \} 23. 代码中可以看出: 24. (1) A类的变量obj可以接受任何B类的实例 25. (2) BImpl实现类的实例不是通过A类自己**new**出来,而是通过setter来由外部传给它。 26. 此时考虑 A类依赖的实例如何从外部注入,就要通过xml定义,Spring容器再依据xml来实例化。 27. 28. 创建一个spring-context.xml 29. <beans> 30. <bean id="B" **class**="\*\*\*\*\*.BImpl"> 实体类名包 31. <bean id ="A" **class**="\*\*\*\*.A"> 32. <proproty name="obj"> 33. <ref bean ="B" 34. </property> 35. </bean> 36. </beans> 37. 这里的配置文件将BImpl实现类和A类加入,并将BImpl作为A类的一个参数。 38. 容器加载通过xml来实例化相关的bean。 39. 通过上面不难发现: 40. (1) A类是通过接口B类来接受BImpl实例,所以 41. 当我们又有新的 B类的实现是,只需要修改xml文件即可。 42. 通过上例可以总结得出: 1.依赖类是通过Spring容器解析xml后来注入的,而不是使用它的类(A)来自己制造,这就是依赖的注入。 2.A类对BImpl类的依赖转移到对B接口的依赖,控制权由类转移到了接口,即由"实现"转移到"抽象"中。 3.通过将对实例的依赖,改为对接口的依赖。是面向接口编程的一个要义。也是程序解耦的一个措施。
还没有评论,来说两句吧...