在讲容器之前,再明确一下知识点。
- BeanDefinition 是 Bean 在容器的描述。BeanDefinition 与 Bean 不是一个东西。
- Bean 是根据 BeanDefinition 创建出来的。也即是我们所说的对象。
BeanDefinition 物料需要有地方存储,Bean 成品需要有地方存。今天我们讲讲仓库。
BeanFactory 家族
此图是默认容器 DefaultListableBeanFactory 的继承, 实现关系图. 我们从右向左来分析下.
- BeanFactory 接口:容器顶级接口,提供了容器最基本的能力,包括获取 bean, 是否包含 bean, 是否单例,获取 bean 类型,Bean 的别名等方法。
- ListableBeanFactory 接口:BeanFactory 的子接口;具有批量获取 Bean 的能力
- HierarchicalBeanFactory 接口:具有访问父容器的能力。有层次的 BeanFactory。
- AutowireCapableBeanFactory 接口:继承 BeanFactory,扩展了自动装配能力。这个接口更多的作用是用于于与其他框架集成,把不在 spring 容器中的 Bean 加入到 Spring 容器生命周期管理中来。此接口很少用
- ConfigurableBeanFactory:定义了 BeanFactory 的配置。继承 HierarchicalBeanFactory 和 SingletonBeanRegistry 接口。实现了此接口的容器,具有层次,单例 BeanDefinition 注册功能。
- ConfigurableListableBeanFactory:大融合接口,除了具有上述接口的能外,还具有: 类加载器, 类型转化, 属性编辑器,BeanPostProcessor, 作用域,bean 定义, 处理 bean 依赖关系, bean 销毁等功能。
- SingletonBeanRegistry 接口: 具有 Bean 的操作能力. 注册, 查询, 获取 Bean 数量等能力. 注意此处的 Bean 是实例. 区别于 BeanDefinition.
- SimpleAliasRegistry:Bean 的别名操作类, 实现了 AliasRegistry. 具有存储 Bean 别名, 注册 Bean 别名, 获取 Bean 别名的功能.aliasMap 属性存储 Bean 别名
- DefaultSingletonBeanRegistry: 除了继承了 SimpleAliasRegistry 的功能外. 最重要的是实现了 SingletonBeanRegistry 接口. 具有存储 Bean 实例, 注册 Bean, 获取 Bean 的能力. 我们定义的被 Spring 管理的 Class 类的实例对象, 以及实例的之间的相互依赖关系都是存储在此类中. 默认常用的容器 DefaultListableBeanFactory 的 Bean 的相关能力. 就是通过间接继承此类来实现的.
/** Disposable bean instances: bean name --> disposable instance */
private final Map<String, Object> disposableBeans = new LinkedHashMap<String, Object>();
/** Map between containing bean names: bean name --> Set of bean names that the bean contains */
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>(16);
/** Map between dependent bean names: bean name --> Set of dependent bean names */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64);
/** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64)
- FactoryBeanRegistrySupport: 提供多工厂 Bean 的支持.FactoryBean 通过其名字我也可以看出是生产 Bean 的 Bean.
- AbstractBeanFactory 抽象类: 承上启下 . 从图中我们看出. AbstractBeanFactory. 通过继承关系, 继承 FactoryBeanRegistrySupport 各种能力. 而且实现了右边部分接口. 已然是比较完备的 Bean 容器了.AbstractBeanFactory 还通过模板模式定义了获取 Bean 的算法骨架,
- AbstractAutowireCapableBeanFactory: . 具有大部分的能力. 实现了 AbstractBeanFactory 定义的模板方法. 其中 doCreateBean 方法逻辑是把一个 BeanDefinition 变成 Bean 的过程. 这个方法非常重要 . 通常我们使用类创建对象. 直接 new 出来. spring 把 BeanDefinition 到 Bean 的过程模板化, 留下了很多扩展点. 留给使用者可以在不同的时刻自定义 BeanDefition 创建 Bean 的过程.
- DefaultListableBeanFactory 常用的默认容器实现, 也是 spring 最常使用的容器类. 看左边 DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口. 这说明什么? 说明 DefaultListableBeanFactory 具有存储 BeanDefinition, 操作 BeanDefinition 的能力.DefaultListableBeanFactory 通过继承关系也具有了 Bean 的存储操作功能.
小结 :
- BeanFactory 体系,接口分明,完美的体现了接口分离原则。
- BeanFactory 体系中有两种存储, 一种是 BeanDefinition 的存储, 另一个是 Bean 的存储.
- DefaultListableBeanFactory 作为最常用的容器类. 不但具有 BeanDefinition 的存储操作功能, 而且通过继承具有 Bean 的存储操作功能.DefaultListableBeanFactory 把存储的 BeanDefinition 通过一定算法创建 Bean 并存储起来 .
BeanDefinition,BeanFactory,Bean 三者关系
通过上面的对各个接口, 类的认识. 我们再来看看三者的关系.
我们向 BeanFactory 容器中注入一个 BeanDefinition。BeanFactory 帮我们存储起来. 当我们想要得到一个 Bean 时.BeanFactory 帮我们把 BeanDefinition 创建 Bean. 并缓存起来. 这个创建过程是可参与的 .
- BeanFactory 保存了 BeanDefiniton 与 Bean.
- BeanFactory 具有使用 BeanDefinition 创建 Bean 的功能
- BeanFactory 允许使用者可以干预 BeanDefinition 生成 Bean 的功能.
BeanFactory 中的扩展点
设计原则之开闭原则说的特别好:说一个软件实体应该通过扩展来实现变化.
很多优秀的框架都有类似的扩展点设计, 列如:
- Tomcat 中的 Filter
- Tomcat 中的 pipline-valve
- springmvc 中的 Interceptor
BeanFactory 中从 BeanDefinition 到 Bean 并不是一下子就完成的. 这有一个过程.spring 正是在这个过程中留下扩展点. 来实现 BeanDefinition 到 Bean 的过程中的各种自定义变化.
从上面我们得知:AbstractAutowireCapableBeanFactory 中有个 doCreateBean() 正是 BeanDefinition 到 Bean 的创建方法. 接下来我们看看这个方法. 有哪些扩展点:
- xxxAware 接口: 使 Bean 可以获得 xxx. 列如实现了 BeanFactoryAware 接口的类,可以在该 Bean 被加载的过程中获取加载该 Bean 的 BeanFactory
- BeanPostProcessor:BeanPostProcessor 接口定义的两个方法,分别在 bean 的初始化方法(InitializingBean 接口,或者 init-method 定义)执行的前后执行
- InitializingBean 接口: 实现了 InitializingBean 接口的类, 执行 afterPropertiesSet
- 自定义的 init-method 方法:
总结:
BeanFactory 是物料与成品仓库,并配生产线,把 BeanDefinition 生产成 Bean。BeanFactory 留下很多扩展点, 方便开发人员可以参与 BeanDefinition 到 Bean 的创建过程.
欢迎大家关注我的公众号【源码行动】,最新个人理解及时奉送。