IoC 概述
IoC 控制反转
IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入。
IoC 容器概述
IOC (Inversion of Control) 控制反转:所谓控制反转,就是当我们需要某个 Bean 时,将 Bean 的名称告知容器,由容器去创建该 Bean,而不是我们手动 new 一个,这里 Bean 创建管理的控制权都交给了容器,所以这是一种控制权的反转。其通俗点讲就是需要什么东西让别人送过来,而不是自己去拿。
DI (Dependency Injection) 依赖注入:就是指当 A Bean 里面需创建 B Bean 时,会在创建 A Bean 的时候,自动将依赖的 B Bean 注入进去,其 B Bean 是被动接受注入而不是自己主动去找。换句话说就是指 A Bean 不是从容器中查找它依赖的 B Bean,而是在容器创建 A Bean 候主动将它依赖的 B Bean 注入给它。
IOC 和 DI 其实归根结底实现的功能是相同的,只是同样的功能站在不同的角度来阐述罢了,不过我们通常喜欢将这两个概念统称为 IOC。当然,在真实场景中,交由 Spring 容器创建的 Bean 泛指在应用程序中的表现层、业务层、持久层等各层对应的 Bean,如 Controller、Service 等;进行数据交互的模型,如 DTO、VO 等就不需交由 Spring 来创建。
所以,容器本质上可以也可以看作是 Bean 工厂,该工厂管理 Bean 的生命周期,以及 Bean 之间的依赖关系。外界也将 Spring 容器称为 IOC 容器。当然,这里容器仅仅是 Spring 的抽象概念,代码中将其具象化为 BeanFactory 或 ApplicationContext,容器功能也由具象化的类进行处理。
org.springframework.beans 和 org.springframework.context 包是 Spring Framework 的 IoC 容器的基础。 Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext。 Bean 工厂接口提供了一种高级配置机制,能够管理任何类型的对象。ApplicationContext 是 BeanFactory 的子接口。
BeanFactory
BeanFactory 是基础类型的 IoC 容器,由 org.springframework.beans.facytory.BeanFactory 接口定义。BeanFactory 是容器最基础的类,它定义了容器的基本功能规范:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
// 根据 bean 的名字,获取在容器中 bean 实例
Object getBean(String name) throws BeansException;
//根据 bean 的名字和 Class 类型来得到 bean 实例,增加了类型安全验证机制。
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
// 提供对 bean 的检索,看看是否在容器有这个名字的 bean
boolean containsBean(String name);
// 根据 bean 名字,判断这个 bean 是不是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
// 根据 bean 名字,判断这个 bean 是不是原型
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
// 根据 bean 名字,判断是否与指定的类型匹配
boolean isTypeMatch(String name, ResolvableType typeToMatch)
throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch)
throws NoSuchBeanDefinitionException;
// 得到 bean 实例的 Class 类型
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit)
throws NoSuchBeanDefinitionException;
// 得到bean 的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
}
在 BeanFactory 里只对容器的基本行为作了定义,其根本不关心你的 Bean 是如何定义怎样加载的。
正如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心。而要知道工厂是如何产生对象的,我们就需要看具体的容器了,也就是 BeanFactory 的子类。
BeanFactory 体系中常用的实现类有:
- ListableBeanFactory:提供容器中 bean 迭代的功能。如返回所有 Bean 的名字、容器中 Bean 的数量等。
- HierarchicalBeanFactory:提供父容器的访问功能,可通过 ConfigurableBeanFactory 的 setParentBeanFactory 方法设置父容器。
- AutowireCapableBeanFactory:为 Spring 容器之外的 Bean ,也就是未交由 Spring 管理的 Bean ,提供依赖注入的功能。
以上三个是 BeanFactory 的直系亲属,这个三个直系亲属下面又派生了两个复杂的容器: - ConfigurableBeanFactory:其继承了 HierarchicalBeanFactory 和 SingletonBeanRegistry 这两个接口,其提供了很多方法,如:定义类加载器、类型转化、属性编辑器、注册依赖 Bean 、销毁 bean 等,且该接口被大多数的容器继承、实现。
- ConfigurableListableBeanFactory:这个接口继承了 ListableBeanFactory、 AutowireCapableBeanFactory、ConfigurableBeanFactory,自身主要提供用于分析和修改 bean 定义以及预先实例化单例 Bean 的方法。
最后是核心容器:
- DefaultListableBeanFactory:它实现了以上所有的接口,在 BeanFactory 体系中可以作为一个独立的容器使用。
BeanFactory 大致的继承关系如下:
ApplicationContext
org.springframework.context.ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。它不仅提供了 BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持。
BeanFactory:Spring 管理 Bean 的顶层接口,我们可以认为他是一个简易版的 Spring 容器。ApplicationContext 继承 BeanFactory 的两个子类:HierarchicalBeanFactory 和 ListableBeanFactory。
- HierarchicalBeanFactory:是一个具有层级关系的 BeanFactory,拥有属性 parentBeanFactory。
- ListableBeanFactory:实现了枚举方法可以列举出当前 BeanFactory 中所有的 bean 对象而不必根据 name 一个一个的获取。
- ApplicationEventPublisher:用于封装事件发布功能的接口,向事件监听器(Listener)发送事件消息。
- ResourceLoader:Spring 加载资源的顶层接口,用于从一个源加载资源文件。ApplicationContext 继承 ResourceLoader 的子类 ResourcePatternResolver,该接口是将 location 解析为 Resource 对象的策略接口。
- MessageSource:解析 message 的策略接口,用不支撑国际化等功能。
- EnvironmentCapable:用于获取 Environment 的接口。
ApplicationContext 的子接口
ApplicationContext 有两个直接子类:ConfigurableApplicationContext 和 WebApplicationContext。
该接口只有一个 getServletContext(),用于给 servlet 提供上下文信息。
ConfigurableApplicationContext
该接口是比较重要的一个接口,几乎所有的应用上下文都实现了该接口。该接口在 ApplicationContext 的基础上提供了配置应用上下文的能力,此外提供了生命周期的控制能力。
WebApplicationContext 接口和 ConfigurableApplicationContext 接口有一个共同的子类接口 ConfigurableWebApplicationContext,该接口将这两个接口进行合并,提供了一个可配置、可管理、可关闭的 WebApplicationContext,同时该接口还增加了 setServletContext(),setServletConfig()等方法,用于装配 WebApplicationContext。
ClassPathXmlApplicationContext
该类是 ApplicationContext 接口的常用实现类,从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作
该图为 ClassPathXmlApplicationContext 的类继承体系结构,它基本上包含了 IOC 体系中大部分的核心类和接口。
AbstractApplicationContext 实现了 ConfigurableApplicationContext 这个全家桶接口,其子类 AbstractRefreshableConfigApplicationContext 又实现了 BeanNameAware 和 InitializingBean 接口。
所以 ClassPathXmlApplicationContext 设计的顶级接口有:
- BeanFactory:Spring 容器 Bean 的管理
- MessageSource:管理 message ,实现国际化等功能
- ApplicationEventPublisher:事件发布
- ResourcePatternResolver:资源加载
- EnvironmentCapable:系统 Environment(profile + Properties) 相关
- Lifecycle:管理生命周期
- Closeable:关闭,释放资源
- InitializingBean:自定义初始化
- BeanNameAware:设置 beanName 的 Aware 接口