IoC (Inversion of Control),是一种设计思想,它把传统上由程序代码直接操控的对象的调用交给容器,通过容器来实现对象组件的装配和管理,由容器来控制对象。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。
对于 IoC 来说,最重要的就是容器,容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。Spring中设计了两个接口来表示容器,分别是BeanFactory、ApplicationContext。
BeanFactory: BeanFactory可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。
ApplicationContext: ApplicationContext比 BeanFactory 多了更多的功能,比如:资源的获取,支持多种消息、资源国际化等,该接口定义了一个 refresh 方法,用于刷新整个容器,即重新加载/刷新所有的 Bean。而且ApplicationContext其实是建立在BeanFactory基础之上的。
![](https://img.haomeiwen.com/i24459569/d9a4cac8c22b71f1.png)
可以看到,ApplicationContext继承自BeanFactory,当又继承了许多其他的接口,完成了对于功能的扩展。
IoC初始化的过程本质上是实例化Bean的过程,关于这个问题可以看下我的这篇文章https://www.jianshu.com/p/93318aad23f4
![](https://img.haomeiwen.com/i24459569/6fccda2258468f86.png)
在这里我就简单的以文字形式进行大纲说明:
- 首先Spring会通过BeanDefintionReader从XML、注解、配置类、或者是其他方式去读取到Bean的配置信息。
- 然后Spring会根据bean的注册表来实例化bean,通过BeanFactoryPostProcessor,在Bean工厂中class.newInstance(),完成对于bean的实例化。然后读取BeanDefintion中的描述信息,通过BeanWapper提供的设置属性的接口进行属性的赋值,完成依赖注入。
在这里提一点,不知道有没有同学会有疑问,为什么Spring要把实例化和依赖注入分成两步呢?这是因为bean与bean之间可能存在着依赖关系。比如说:beanA依赖beanB,但是在加载beanA时,可能beanB还没有加载好,也就无法从容器中获取beanB。所以Spring将实例化和依赖注入分成两步,如果Bean存在着依赖关系,那么就使用占位符ref暂时代替。等到调用getBean方法,也就是真正进行依赖注入的时候,如果碰到属性是ref的,那么就从容器中获取这个bean,然后注入到实例中——称之为依赖注入(Dependency Injection) - 将bean实例化完之后,Spring就会将这些bean实例放到Spring容器中。
- 至此,应用程序就可以使用由Spring容器管理的bean了,只有当Spring容器销毁的时候,这些bean才会销毁。
网友评论