声明:我已委托「维权骑士」(rightknights.com)为我的文章进行维权行动。
通过上一章 《理解Spring系列——什么是控制反转(Inversion of Control, IoC)》 ,我们了解到IoC编程模式的本质,通过协议约定来分离when-to-do和what-to-do两个关注点,实现模块间的解耦。
而在Spring Framework中,BeanFactory绝对是Spring IoC的核心担当: BeanFactory
在Spring中的主要作用,通过抽象Bean实例化的具体过程(体现在BeanDefinition定义),借助依赖注入(Dependency Inject,DI)的能力,实现基于元数据的业务对象自动装配,可以理解成增强版的 Guice ,如下图所示。
在Spring Framework中, BeanFactory
作为非常基础的接口存在,提供了Bean注册能力(包括Bean查询、类型判断、scope判断等基础能力);在继承体系上,可以分成 BeanFactory实现类
和 ApplicationContext
两条继承线路。
两者的关系如下: BeanFactory实现类
属于外观模式的子系统(SubSystem)承担着外界提供Bean对象的主要责任,是功能实现的主体; ApplicationContext
作为 BeanFactory实现类
的外观系统(Facade System),通过 BeanFactory
提供的接口结合具体的业务场景解析元数据( BeanDefinition
)的解析和注册,并进行Bean对象的初步加载。 另外, ApplicationContext
继承于接口 BeanFactory
,并在 BeanFactory
的基础上,提供AoP能力的集成、消息资源的管理、事件发布机制、以及基于特定场景(Web系统、文件系统)的能力封装等主要功能。
BeanFactory
完整的继承关系如下图所示:
从图中可以看出, BeanFactory
的主要实现类包括 StaticListableBeanFactory
、 DefaultListableBeanFactory
、 SimpleJndiBeanFactory
等三个公共类,分别面向 静态场景 、 默认枚举配置场景 和 JNDI 等场景,对应的实现思路也不尽相同。
StaticListableBeanFactory
可以看做是基于 Map<String,Object>
的简单封装, 不包括Bean的实例化过程 ,需要用户手动注册后才可以使用,不具备依赖注入能力,是 BeanFactory
最为简单的实现; DefaultListableBeanFactory
是Spring BeanFactory
的默认实现,是Spring IoC容器中最为复杂的部分,在后续的章节我们会进行分析; SimpleJndiBeanFactory
则是基于JNDI场景发现对应Bean。 类 DefaultListableBeanFactory 的继承关系如下图所示, 从中我们可以基本上了解到 类 DefaultListableBeanFactory 的基本功能。
DefaultListableBeanFactory
的接口继承关系 从 接口实现 上看,类 DefaultListableBeanFactory 主要实现了以下基础的接口:
AliasRegistry
:属于spring-core模块(别名能力不限制于Bean Name场景,因此定义在core模块中),提供String类型别名相关能力,对应的实现类为 SimpleAliasRegistry ,可以看做是简易版的 Map<String,String> 抽象能力,提供别名的增删改查相关能力; SingletonBeanRegistry
:属于spring-beans模块,提供单例bean对象的注册和查询能力,可以看做是简易版的 Map<String,Object> ; ListableBeanFactory:
:属于spring-beans模块,在 BeanFactory 的基础上提供更进一步的非精确化查询能力,支持基于类型( Class
和 ResolvableType
)的查询能力,返回的结果支持beanName 和 Map<BeanName,Bean>
; HierarchicalBeanFactory
: 属于spring-beans模块,提供多层次的BeanFactory结构,允许多个BeanFactory之间存在继承关系。例如在 WebApplicationCpontext 的使用场景中, WebApplicationContext 依赖于基于XML配置的 XMLApplicationContext等; AutowireCapableBeanFactory
:属于spring-beans模块,提供基于bean的 自动装配 能力,包括依赖查找(Dependence Lookup)和依赖注入(Dependence Inject)能力; ConfigurableBeanFactory
: 属于spring-beans模块,提供 DefaultListableBeanFactory 相关数据的读取和配置接口,同时提供销毁bean 的能力。
ConfigurableListableBeanFactory
在 AutowireCapableBeanFactory
提供了部分依赖的设置能力,例如,注册特定类型的依赖默认值( registerResolvableDependency(Class<?> dependencyType, Object autowiredValue)
),判断某个bean依赖关系是否存在候选集合( boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
),依赖忽略特定的接口或者类型的依赖注入( ignoreDependencyType(Class<?> type)
、 void ignoreDependencyInterface(Class<?> ifc)
)。依赖候选集的查询需要容器提供基于类型查询对应的bean的能力,因此接口 ConfigurableListableBeanFactory
继承了接口 ListableBeanFactory
,因此,在实现的所有接口中, ConfigurationListableBeanFactory
的继承关系是最为复杂的,聚合了很多抽象的能力, 是最接近实现类 DefaultListableBeanFactory
的接口 ,因此在spring 在对外提供BeanFactory预处理接口 BeanFactoryPostProcessor
的时候,对应的方法签名是 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
,而不是
void postProcessBeanFactory(BeanFactory beanFactory)
BeanFactoryPostProcessor#postProcessBeanFactory
中传入的参数是ApplicationContext。 BeanDefinitionRegistry
提供了基于beanName的 BeanDefinition 的注册、删除和查询能力。 DefaultListableBeanFactory
的类继承关系 DefaultListableBeanFactory
的类继承关系,自上到下依次对应的是 Object <- SimpleAliasRegistry <- DefaultSingletonBeanRegistry <- FactoryBeanRegistrySupport <- AbstractBeanFactory <- AbstractAutowireCapableBeanFactory <- DefaultListableBeanFactory 。
从上到下,BeanFactory 关注点变得越来越具体,逻辑也变得越来越复杂,对应的能力逐渐强大:从最初的别名注册能力,到bean对象的注册管理和 FactoryBean
对象的管理,再到BeanFactory配置管理,自动装配能力的实现,最后才是BeanDefination注册管理,支持根据BeanDefination进行对象的实例化。
BeanFactory
vs FactoryBean
FactoryBean
当你向容器注册名字为 factoryBeanName 的 FactoryBean的时候,你向容器注册的是 名字为&factoryBeanName的FactoryBean的对象,,通过factoryBeanName获取到的是 FactoryBean#getObject
返回的对象,该对象不受Spring 容器管理,具体参考 What’s a FactoryBean? 。 FactoryBean
简化一部分实例过程,减少无关Bean的注册。例如 AbstractEntityManagerFactoryBean
相关实现。 @Configuration public class FactoryBeanDemo { public static final String beanName = "user"; @Bean(beanName) public FactoryBean<User> factoryBean() { return new FactoryBean<User>() { public User getObject() { User user = new User(); user.setName("mijack"); return user; } public Class<?> getObjectType() { return User.class; } }; } public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(FactoryBeanDemo.class); System.out.println(applicationContext.getBean(beanName) instanceof User);// true System.out.println(applicationContext.getBean(beanName) instanceof FactoryBean); // false System.out.println(applicationContext.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) instanceof User);//false System.out.println(applicationContext.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) instanceof FactoryBean);//true System.out.println(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, User.class));// [user] } }
从 ApplicationContext
继承的接口上看,接口 ApplicationContext
继承了接口 ListableBeanFactory
、 HierarchicalBeanFactory
、 EnvironmentCapable
、 MessageSource
、 ApplicationEventPublisher
、 ResourcePatternResolver
,提供IoC容器能力、环境管理、事件发布机制、事件发布-响应机制、资源定位加载、i18n的能力。
从 ApplicationContext
实现的子类上看,ApplicationContext根据不用应用场景分成不同的实现类:
图中中蓝框部分通过 ApplicationContext
-> ConfigurableApplicationContext
-> AbstractApplicationContext
-> AbstractRefreshableApplicationContext
-> AbstractRefreshableConfigApplicationContext
-> AbstractRefreshableWebApplicationContext
& AbstractXmlApplicationContext
的继承体系实现了相关功能,但是这样存在一定问题:不同场景下,我文件加载的方式都要重新实现一遍,例如实现XML的配置加载,需要分成文件系统和Web应用两种不同的实现类,代码复用度太低。
为了避免上述情况,进一步提高代码的利用率,Spring 提出 GenericApplicationContext
类继承体系(红色框的实现体系): GenericApplicationContext
实现了接口 BeanDefinitionRegistry
,将资源注册过程从核心流程中剥离出来,特定场景下数据加载解析,有子类实现,提供友好的API接口。不同于 AbstractRefreshableApplicationContext
(维护内部的 BeanFactory
,支持刷新时重新创建 BeanFactory ), GenericApplicationContext
中的 beanFactory 支持从外界导入,为了避免复杂的状态管理, GenericApplicationContext
默认不支持容器的重新刷新。
Previous
理解Spring系列——什么是控制反转(Inversion of Control, IoC)