这几天突然想看起spring的源码,顺便将ioc的东西梳理一遍。写之前先抛出问题
问题
1、使用ioc的作用在哪里?它比传统的实例化对象的好处在哪里?
2、ioc统一bean的创建,自动维护bean的依赖关系,那请问,spring容器是怎么实例初始化配置文件中的bean?(详细就可以参考ClassPathXmlApplicationContext的源码分析)。
见博客https://www.cnblogs.com/wade-luffy/p/6072460.html
一、依赖注入-控制反转的好处是什么?为什么我们要使用它们?
我们首先理解下字面意思,依赖反转,就是把依赖关系倒过来呗,那正依赖是什么样子呢?
正依赖
正着的时候是上层建筑依赖下层建筑,依赖方式是在自己构造的时候把下层先构造好,比如car和wheel :
class car{ Wheel wheel ; public car(){ wheel = new wheel(); } } public class wheel{ }
Main方法:Bird bird = new Bird();
这就是典型的上层依赖下层,(为了更方便理解,可以直接把依赖理解为依赖构造函数),这样的坏处是如果下层的构造函数改了,增减了参数,那上层的构造函数也得加上类似的参数,那如果上层还有上层呢?就要一层一层加上去(如果这里不理解的话建议戳上面的链接看知乎原文,答主说的肥肠清晰)。唯一的好处是Main方法倒是很简洁。
依赖反转
这里按照上面的理解(为了更方便理解,可以直接把依赖理解为依赖构造函数)
叫做取消依赖更合适一些,就是上层不再依赖于下层的构造函数,怎么做到的?下层直接构造好,把整个下层当做参数传进来:
class car{ Wheel wheel ; public Car(Wheel w){ wheel = w; } } public class Wheel{ }
Main方法:Car car = new Car(); bird = new Bird(wing);
这样做,如果Wing类构造函数加个参数,只需要改Main方法就行了,坏处是如果建筑层数很多的话,需要从低到高一个一个new,如果用到的地方很多,每次创建一个顶层对象都要这样那真的很麻烦
其中setter方式的依赖注入我们也顺带讲下。
---------setter方式的依赖注入,
class car{ Wheel wheel ; public Car(){ } public setWheel(Wheel wheel ){ this.wheel = wheel; } } public class Wheel{
写的一个setter方式依赖注入的demo:
这就是一个非常完整的setter依赖注入的例子了,其中UserDaoImpl对象和UserDaoImpl对象的创建就是靠spring容器管理的,回到上面抛出的问题,spring容器是怎么实例初始化配置文件中的bean?(详细就可以参考ClassPathXmlApplicationContext的源码分析)。
看源码脑壳疼,https://www.cnblogs.com/wade-luffy/p/6072460.html
总结:依赖注入方便创建高内聚、低耦合的软件,降低了耦合性(将依赖关系从代码中抽出)
总结,依赖注入,我们可以发现上层不再依赖下层,上层对象不再关系下层对象构建的方式细节,它只是提供一个set方法或者构造方法的入参,将下层对象传入进来。比如人需要用一把锤子, 以前可能是人自己去制造这把锤子,会关注着把锤子构建的过程。依赖注入的话,人不再关心这把锤子是怎么构建出来的了,它只需要去别人给他一把锤子,他就开始工作。着降低了耦合性。