前言
IoC本身来说并不是一种技术,而是一种思想。在spring开发中我们常常使用,但有时候想起来这个概念时,却不知道从何说起。本文就来谈谈spring中的核心概念——IoC。
正文
IoC概念
IoC(Inversion of Control)中文名“控制反转”,它是一种设计的思想。Ioc代表着你将对象交给容器来控制,而不是自己控制对象本身。为什么是反转呢?举个例子:
我们在传统的开发中,通常是通过new关键字在对象内部使用另一个对象,是我们主动去创建依赖的对象。而Ioc则是有一个专门的容器来创建这些对象。我们通过自己主动控制生成对象的方式也叫做正转,而使用容器控制创建对象并注入的方式,就称作反转。
IoC的作用
IoC常常被用在大型框架上,由IoC容器去创建去查找依赖的对象,由容器去注入对象,使得对象之间是松耦合的,方便测试与功能的复用,也利于维护,让整体架构更加灵活。
DI
前面提到了注入,也就是DI(Dependency Injection),即“依赖注入”,是指组件之间的依赖关系由容器在运行期决定,即容器动态地将某个依赖关系注入到组件中。通过依赖注入,我们只需完成业务逻辑,无需关心资源的来源于由谁决定,一切都由容器帮忙注入依赖。
IoC的技术实现
既然已经清楚IoC的概念,那IoC容器又是怎么完成依赖注入呢?常见的方式有两种,构造器方法注入与setter注入。
构造器注入是指在对象创建时,所依赖的对象便以参数形式传入该对象中。假设在A类中需要B类:
1 | public A(B b){ |
而setter方法注入则是在需要的时候才执行注入。
1 | public void setB(B b){ |
而无论是哪种方法,IoC容器都帮你执行了,你无需关心注入的过程。
IoC容器
这里就简单介绍下IoC容器。
Spring 提供了两种IoC容器,BeanFactory和ApplicationContext,而ApplicationContext是BeanFactory的子类。BeanFactory 和 ApplicationContext 的区别有:
BeanFactory:是Spring中最底层的接口,只提供了最简单的IoC功能,负责配置,创建和管理bean。
在应用中,一般不使用 BeanFactory,而推荐使用ApplicationContext(应用上下文),原因如下。
ApplicationContext:
- 继承了 BeanFactory,拥有了基本的 IoC 功能;
- 除此之外,ApplicationContext 还提供了以下功能:
- 支持国际化;
- 支持消息机制;
- 支持统一的资源加载;
- 支持AOP功能;
IoC容器初始化与依赖注入
我们知道,IoC容器负责管理对象,而spring中最基本的一个对象就是Bean。
Bean的定义与初始化是两大步骤,Bean在定义后,IoC容器才将其初始化并注入到其他对象中。
Bean的定义有3步:
- Resource 定位
Spring IoC 容器先根据开发者的配置,进行资源的定位,在 Spring 的开发中,通过 XML 或者注解方式查找资源。 - BeanDefinition 的载入
这个时候只是将 Resource 定位到的信息,保存到 Bean 定义(BeanDefinition)中,此时并不会创建 Bean 的实例 - BeanDefinition 的注册
这个过程就是将 BeanDefinition 的信息发布到 Spring IoC 容器中。
但此时Bean并没有被初始化,只是在容器中被定义了。在Spring Bean的配置中,有个配置选项lazy-init,指定是否初始化Bean,默认值为false,即自动初始化,而设置为true则只有当使用getBean方法获取Bean时,才会进行Bean的初始化,完成依赖注入。
如何实现IoC容器?
实现一个IoC容器有以下几个步骤。
- 通过注解或者配置文件,查看A类的依赖对象是哪个类,获取类名。
- 使用反射API,将类名实例化成对象实例。
- 将实例化对象通过构造函数或者setter方法,传递给A类。
其实Spring就是基于以上几个步骤实现IoC,IoC就是工厂模式的升级版。
总结
本文基本上都是基础知识,重点讲了IoC的概念,并顺便谈了IoC的实现原理,之后有需要的话可能会深入spring源码了解更多IoC的细节,比如BeanFactory和ApplicationContext。