IoC(Inverse of Control)控制反转,是Spring的两大特点之一
IoC通过两种方式实现:依赖查找(DL)和依赖注入(DI)
DL已经被抛弃,因为他需要用户自己去使用API进行查找资源和组装对象。即有侵入性,与Spring的无侵入性相违背
DI是Spring目前使用的方式,容器负责组件的装配。Spring支持的构造函数注入和属性注入。
构造注入
通过一个旧的例子来说明构造注入,墨攻中,刘德华饰演墨者革离,守军询问他是谁,他回答"墨者革离"
public class MoAttack{//编写一个剧本成员 private GeLi geli;//设置一个角色革离 public MoAttack(GeLi geli){//在构造函数进行注入,该成员为革离 this.geli = geli; } public void cityGateAsk(){//回答守军 geli.responAsk("墨者革离"); } } public class Director{ public void direct(){ Geli geli = new LiuDeHua();//实例化一个Geli对象 MoAttack moAttack = new MoAttack(geli);//通过构造函数注入 moAttack.cityGateAsk();//结果返回的是墨者革离,而非刘德华 } }从上面的例子我们可以看出来,当守军问"来者何人"的时候,无论他是刘德华,还是张德华,只要是饰演革离的人都是回答"墨者革离",但是很重要的一个问题,主角是不是每次都会出场,如果不是我们应该怎么做?
属性注入
public class MoAttack{//编写一个剧本成员 private GeLi geli;//设置一个角色革离 public void setGeli(GeLi geli){//通过set方法,属性注入,当需要革离的时候才分配革离的演员 this.geli= geli; } public void cityGateAsk(){//回答守军 geli.responAsk("墨者革离"); } } public class Director{ public void direct(){ Geli geli = new LiuDeHua();//实例化一个Geli对象 MoAttack moAttack = new MoAttack();//通过构造函数创建一个剧本成员 moAttack.setGeli(geli);//通过属性setter注入依赖,安排革离演员 moAttack.cityGateAsk();//结果返回的是墨者革离,而非刘德华 } }通过属性注入的方式,我们可以避免每一次构建MoAttack都需要注入一个GeLi对象。这样就可在不同的场景通过setter注入不同的角色
对于IoC来说,最重要的就是容器。容器管理者Bean的生命周期。
Spring设计了两类容器
BeanFactory,Spring的基础设施,面向Spring。只提供注册(put),获取(get)两个功能。ApplicationContext,面向Spring框架的开发者。图片转载自https://www.cnblogs.com/zffenger/p/5813470.html
上述是较为完整的ApplicationContext类继承体系
ClassPathXmlApplicationContext的大概构造过程为
用户构造ClassPathXmlApplicationContextClassPathXmlApplicationContext首先访问高级容器中的refresh方法,这个是个模板方法,需要回调子类(低级容器)的refreshBeanFactory方法,这个方法的作用是使用低级容器加载所有BeanDefinition和Properties到容器中低级容器加载成功后,高级容器开始处理一些回调。(功能越来越多,越来越迷茫)BeanFacotory的IoC只需要两个步骤:
加载配置文件,解析成BeanDefinition放在Map里调用getBean的时候,从BeanDefinition所属的Map里,拿出Class对象进行实例化,同时,如果有依赖关系,将递归调用getBean方法-完成依赖注入Application包含低级容器的功能,当他执行refreesh模板方法的时候,将刷新整个容器的Bean,同时作为高级容器,包含太多的功能,一句话,它不仅仅是Ioc。他支持不同信息源头,支持 BeanFactory 工具类,支持层级容器,支持访问文件资源,支持事件发布通知,支持接口回调等等。