庞大的BeanFactory家族
DefaultListableBeanFactory
是支撑ApplicationContext底层的BeanFactory,它有一张错综复杂的继承关系图......
可以看到继承关系图中的组件大致分为三类:
BeanFactory
:一些用来定义功能的BeanFactory接口以及一些提供了基础模板功能的抽象BeanFactory实现类ListableBeanFactory
:一种可枚举全部Bean实例的Bean工厂HierarchicalBeanFactory
:一种具有层次结构的Bean工厂,它可以有自己的父工厂ConfigurableBeanFactory
:提供一些配置的Bean工厂AutowireCapableBeanFactory
:可以完成自动装配的Bean工厂- ...
Registry
:一些注册表,提供了不同种类信息的注册AliasRegistry
:提供Bean的别名注册SingletonBeanRegistry
:提供单例对象的注册和缓存BeanDefinitionRegistry
:BeanDefinition注册处,BeanDefinition描述了如何构造Bean- ...
BeanFactory相关接口
接下来的内容将极致枯燥,基本和读API没有区别,但YHN,若你今后再次陷入需要背诵八股文的境地,请回来耐心的读这篇文章......
BeanFactory接口
官方文档:BeanFactory
是一个持有多个bean definition(后文称bean定义)的对象,每一个bean定义都被一个唯一的字符串标识。根据bean定义的不同,工厂可以返回一个独立的对象(prototype模式)或单例的对象(singleton模式)。
bean definition向Spring描述了如何创建一个对象,如何给构造器传参,传递什么参数等,你可以理解为你在XML中定义的那些。所以BeanFactory并不是Bean的容器,而是Bean的创建器,它根据bean定义创建Bean对象,所以叫Bean工厂。我之前一直把它理解为Bean的容器了.....
典型的getBean
方法,用于创建一个Bean:
Object getBean(String beanName)
:返回一个beanName对应的实例,根据bean对应的bean定义的不同,返回的可能是单例的也可能不是。bean定义中描述了该对象是单例还是非单例。Object getBean(String name, Object... args)
:和上一个一样,不同的是,这有一个args
参数,这是允许用户使用自己的参数替换bean定义中描述的<T> T getBean(Class<T> requiredType)
:这一类getBean
使用类型查找,主要为保证类型安全
下面的方法不直接创建Bean,而是返回一个ObjectProvider,允许延时按需创建,并且支持存在性和唯一性校验:
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType)
下面是一些其它的基础方法:
boolean containsBean(String beanName)
:是否存在对应beanName的bean定义,或者通过外部注册了一个singleton实例?(当我们了解到SingletonBeanRegistry时会详谈)boolean isSingleton(String beanName)
:该beanName对应的bean是一个共享单例bean吗?换句话说,每次getBean总是返回一个对象吗?boolean isPrototype(String beanName)
:该beanName对应的bean是一个独立原型吗?换句话说,每次getBean都是返回一个新创建的对象吗?String[] getAlias(String name)
:获取给定beanName的别名
够了,我们不是API文档,所以就介绍这些吧,小总结
- BeanFactory中持有一堆bean定义,它会根据这些定义在你getBean时为你创建bean实例
- BeanFactory接口并未约束如何获取这些bean定义,可能是基于XML,可能是注解,在一些基础的BeanFactory中,甚至暴露了接口让用户自行传入
- BeanFactory中的bean分为单例和原型两种,我个人感觉这里原型这个命名不太妙,虽然原型模式的意思就是给一个对象模板,每次基于模板创建新的对象,但实际上单例也是基于原型模板创建的,只不过需要有东西来负责保存这个Singleton对象,以让第二次getBean时返回这个对象
- BeanFactory也没约束实现类如何保存单例对象
ListableBeanFactory接口
ListableBeanFactory是一种可枚举全部bean实例的Bean工厂,用户无需根据所有名字一个一个的查找
boolean containsBeanDefinition(String beanName)
:获取制定bean定义是否存在,和BeanFactory中的containsBean
的区别是,它不考虑工厂的层次结构,只返回本工厂中的bean定义int getBeanDefinitionCount()
:获取bean定义的数量,也是只返回本工厂中的bean定义数量String[] getBeanDefinitionNames()
:获取本工厂中所有bean定义的名字
接口还提供了一些和注解相关的接口:
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType)
:返回具有指定注解的Bean名列表,通过FactoryBean创建的对象将被初始化以确定类型Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
:返回具有指定注解的Bean,通过FactoryBean创建的对象将被初始化以确定类型<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
:返回bean指定的注解
接口重新定义了几个和BeanProvider相关的接口,都是为其加上了allowEagerInit
参数,这里只列出一个
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit)
:ObjectProvider的流式访问是否会初始化lazy-init的单例对象以及通过FactoryBean创建的对象
HierarchicalBeanFactory
HierarchicalBeanFactory是一种提供层次关系的Bean工厂
BeanFactory getParentBeanFactory()
:获取父bean工厂boolean containsLocalBean(String name)
:本地是否包含指定bean?不考虑祖先工厂
ConfigurableBeanFactory
该接口提供了对Bean工厂的基本设置方法,所有有关BeanFactory的配置设置的方法都在这个接口中。大部分BeanFactory都实现了该接口,但这个接口暴露的方法不应该被应用程序代码使用,它们应该坚持使用BeanFactory
和ListableBeanFactory
中定义的方法,本接口中的方法只应该被框架内部使用。
我这里挑几个我觉得有趣的介绍下:
void setBeanClassLoader(ClassLoader beanClassLoader)
:设置bean类的类加载器,默认使用线程上下文加载器void setTypeConverter(TypeConverter typeConverter)
:设置类型转换器,BeanFactory将使用它做bean属性值、构造器参数值等的转换void addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
:添加Bean的后处理器,它们将在Bean被该工厂创建时被应用void registerScope(String scopeName, Scope scope)
:注册scope,Spring原生只支持singleton和prototype,这里给了动态定义Scope的能力,我不知道SpringMVC中的request、session等scope是否是使用该方法定义的BeanDefinition getMergedBeanDefinition(String beanName)
:考虑一个BeanDefinition在当前工厂和其祖先工厂中都有定义,该方法可以在必要时合并子工厂中的bean定义和夫工厂中的bean定义void setCurrentlyInCreation(String beanName, boolean inCreation)
:用来设置某一个bean当前是否在创建过程中,仅限容器内部使用void registerDependentBean(String beanName, String dependentBeanName)
:为给定bean注册一个依赖bean,在给定bean销毁前被销毁
可以看出这个BeanFactory有一些针对工厂配置时的设置,比如设置bean的类加载器,也有一些针对工厂运行时的设置,比如设置某一个bean当前是否在创建过程中。
AutowireCapableBeanFactory
那些想要提供自动装配能力的bean工厂需要实现这个接口,应用代码永远不要用到该接口里的方法,它们应该坚持使用BeanFactory和ListableBeanFactory的方法完成需求
该类的作用实际上是给第三方的不受Spring管控的bean进行自动装配,比如JUnit和Spring整合的测试类,实际上那个测试类并不是一个Spring管理的Bean容器,但它却能够通过 @Value
、@Resource
以及@Autowired
注解注入属性,这便是通过AutowireCapableBeanFactory
完成的。
下面是一个小例子:
static class OuterBean {
@Autowired
public Person person;
}
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 注册一个bean进去
factory.registerSingleton("person", new Person("yudoge"));
// 创建普通对象
OuterBean bean = new OuterBean();
// 使用容器中的bean装配普通对象
factory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
// Person(name=yudoge),装配成功
System.out.println(bean.person);
// throw NoSuchBeanDefinitionException,容器中并没有这个bean
System.out.println(factory.getBean(OuterBean.class));
}
这个接口中的方法都是与第三方Bean交互的,比如
createBean
会以所有SpringBean初始化的完整流程创建第三方Bean,但容器中并没有相关的bean definition,所以容器也不会纳管这个bean。
介绍下它的部分方法:
<T> T createBean(Class<T> beanClass)
:创建一个指定类型的第三方bean,执行完整的bean初始化流程,包括所有的BeanPostProcessor、所有标准化Bean回调,填充带注释的属性和方法,不指定是使用哪种注入方式(BY_TYPE、BY_NAME)void autowireBean(Object existingBean)
:填充给定的bean实例,通过后实例化回调以及bean属性的后处理器(比如注解驱动注入)Object configureBean(Object existingBean, String beanName)
:根据bean工厂中beanName对应的bean定义去配置Bean,比如属性等
Registry相关接口
AliasRegistry
管理别名的简单接口,是BeanDefinitionRegistry
的父接口。
只有简单的四个方法
Spring beanfactory包下唯一封装了bean定义注册的接口,内容也很简单,是对bean定义的增删改查,所以也没啥可介绍的
SingletonBeanRegistry
提供共享单例bean的管理,可以被BeanFactory实现,以统一的方式暴露单例bean管理功能。
void registerSingleton(String beanName, Object singletonObject)
:使用beanName注册一个单例对象,会假设这个对象已经被完全初始化了,不会执行任何初始化回调和销毁回调Object getSingleton(String beanName)
:获取一个单例对象,只会返回已有的单例对象,对于singleton的bean定义,不会创建一个单例对象并返回
其它的
count
和contains
等方法都是只针对已有的单例对象的,和getSingleton
一样。
DefaultSingletonBeanRegistry实现
DefaultSingletonBeanRegistry
是Spring中用来注册单例Bean实例的核心类,它继承了SimpleAliasRegistry
,所以有开箱即用的别名注册功能,实现了SingletonBeanRegistry
相关接口。
该类在基础的单例注册上提供了很多新功能:
- 支持
DisposalBean
实例的注册,会在注册处shutdown时销毁 - 支持注册bean之间的依赖关系,以强制执行适当的销毁顺序
- 该类不了解有bean定义这个概念,也不了解特定的bean创建流程
属性
Map<String, Object> singletonObjects
:单例对象的缓存,beanName => 实例Map<String, ObjectFactory<?>> singletonFactories
:单例对象工厂的缓存,beanName => 对应工厂。所以该类是支持通过工厂完成单例bean的懒创建的Map<String, Object> earlySingletonObjects
:早期单例对象缓存,beanName => 实例。目前尚不明确早期单例对象是啥。gpt给出的解释是,在bean的创建过程中,它们有可能依赖其它bean,导致它们并没有完全初始化完成,该缓存保存的就是这些没有完全初始化完成的bean。一旦它们初始化完成,就被从这个cache移动到singletonObjects
Set<String> registeredSingletons
:已注册的单例对象,按照注册顺序排列它们的beanName,是个LinkedHashSetSet<String> singletonsCurrentlyInCreation
:当前在创建过程中的beanNameSet<String> inCreationCheckExclusions
:被创建过程检查排除的beanNameMap<String, Object> disposableBeans
:DisposableBean缓存,beanName => 实例Map<String, Set<String>> containedBeanMap
:bean之间的包含关系的缓存,包含beanName => 被包含beanName集合Map<String, Set<String>> dependentBeanMap
:bean之间依赖关系的缓存,beanName => 依赖它的beanName集合Map<String, Set<String>> dependenciesForBeanMap
:bean之间依赖关系的缓存,beanName => 它依赖的beanName集合
小总结:从它的属性中我们可以看出,该类并非只是简单实现了SingletonRegistry的基础功能,还提供了一些供子类使用的其它功能,如支持懒创建、支持对象之间具有依赖关系并支持标记哪些对象目前是部分创建对象、支持注册DisposalBean
registerBean
该方法来自接口,很简单,就是将一个已经完全初始化完毕的对象注册到注册表中:
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
// 若已有该beanName
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
addSingleton(beanName, singletonObject);
}
}
在addSingleton
中可以看出,该方法的目的就是将一个已经完全初始化完毕的对象添加到注册表中,所以它会移除掉懒加载器,移除掉早期对象表中的相关内容,并确保添加到singletonObjects
和registeredSingletons
中,而且从它的写法中可以看出,应该还有其它的位置调了这个,不然没必要四个表都操作:
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
getSingleton
也是接口中的方法实现,这里调用了内部的一个同名方法,不过多了一个参数:
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
内部的getSingleton
尝试获取完整对象、早期对象,甚至在allowEarlyReference
时还会尝试使用对应的工厂创建对象,创建后的对象被加入到早期bean表里,对应工厂被移除:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 不加锁快速检查是否已有完整bean
Object singletonObject = this.singletonObjects.get(beanName);
// 不存在,并且在创建了
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 不加锁快速获取早期bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 不存在并且allowEarlyReference == true
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 加锁后double check
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 获取有没有对应的懒加载工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 如果有,创建并添加到早期bean表中,并将对应工厂移除
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
刚刚发现,我一直说调用工厂创建单例对象,但貌似
ObjectFactory
并不约束getObject
时对象是否是新创建的,实际上,它只是一个对象的holder,getObject
可以返回一个单例对象也可以返回一个非单例对象,这个对象如何创建或获取都没有约定。
同时,该类还提供了由外部传入一个ObjectFactory
,并在找不到时使用外部的工厂创建对象的getSingleton
方法,该方法在需要创建单例bean时,创建出的bean将跨越早期对象,直接加入singletonObjects
,我也不知道为啥
一些基础方法
containsSingleton
只检查完整单例对象表
@Override
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
getSingletonNames
和getSingletonCount
检查所有注册的单例对象,不管是否是早期的
@Override
public String[] getSingletonNames() {
synchronized (this.singletonObjects) {
return StringUtils.toStringArray(this.registeredSingletons);
}
}
@Override
public int getSingletonCount() {
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
一些和singleton是否处于创建过程中相关的方法:
// 设置创建状态,如果没在创建,实际上只是将它添加到不进行创建检查的表中,否则加入
public void setCurrentlyInCreation(String beanName, boolean inCreation) {
Assert.notNull(beanName, "Bean name must not be null");
if (!inCreation) {
this.inCreationCheckExclusions.add(beanName);
}
else {
this.inCreationCheckExclusions.remove(beanName);
}
}
// 当前是否在创建过程中,根据排除表和singletonsCurrentlyInCreation表判断
public boolean isCurrentlyInCreation(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
}
protected boolean isActuallyInCreation(String beanName) {
return isSingletonCurrentlyInCreation(beanName);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
实际上该类的所有方法都是增删改查表的过程,我也就不再分析了,要注意的是,
containedBean
的注册也会导致有包含关系的两个bean被注册到依赖关系表中,注释上说这是为了让它们也遵循销毁顺序
FactoryBeanRegistrySupport
是用于支持那些需要处理FactoryBean
的SingletonRegistry的基础支持类,与DefaultSingletonBeanRegistry
整合
FactoryBean
如果BeanFactory中的某个对象实现了FactoryBean
,它将被作为bean对象的工厂,而作直接作为一个bean对象暴露。
它可以支持单例也可以是非单例,可以在启动时就创建对象,也可以按需惰性创建
容器只会负责FactoryBean的生命周期管理,而非底层对象的,如有需要,FactoryBean需要实现类似DisposalBean的接口,然后将对应callback转发给底层bean。
FactoryBeanRegistrySupport中只有一个属性:
Map<String, Object> factoryBeanObjectCache
:被factoryBean创建的单例对象的缓存,factoryBeanName => 单例对象
方法:
Class<?> getTypeForFactoryBean(FactoryBean<?> factoryBean)
:确定给定FactoryBean的类型Object getCachedObjectForFactoryBean(String beanName)
:根据factoryBeanName获取被缓存的单例对象,这里可以看出,beanFactory内的beanName实际上就是这里理解的factoryBeanNameObject getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)
:获取给定factoryBean中暴露的对象protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { // 如果factoryBean中是单例,并且注册处中有该单例(我想注册处中存的也是FactoryBean吧) if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); // 如果缓存里没有 if (object == null) { // 从factoryBean获取 object = doGetObjectFromFactoryBean(factory, beanName); Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // 只有在执行上面的getObject调用期间没有人已经把它放到缓存中时才会执行后处理和存储 if (shouldPostProcess) { if (isSingletonCurrentlyInCreation(beanName)) { // 暂时返回尚未后处理的对象,并且没有存储到缓存 return object; } beforeSingletonCreation(beanName); try { // 后处理,允许对对象进行代理、包装、替换等 // 该类默认只返回原始对象,由子类自行重写 object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", ex); } finally { afterSingletonCreation(beanName); } } // 写缓存 if (containsSingleton(beanName)) { this.factoryBeanObjectCache.put(beanName, object); } } } return object; } } else { // prototype,没那么讲究,直接创建并后处理 Object object = doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } return object; } }
总结
该类只是一个BeanFactory实现类的helper类,继承了这个helper的实现类可以得到这些关于FactoryBean类型bean的辅助方法
AbstractBeanFactory
我们要开始复杂的BeanFactory实现了,先来看一个基础模板类
该类提供的能力:
- 单例缓存,通过
DefaultSingletonBeanRegistry
- 单例/原型区分
FactoryBean
处理- 别名
- BeanDefinition合并
- Bean销毁
- BeanFactory层次结构
子类需要实现的主要方法:
getBeanDefinition
:给定一个beanName,用于找到对应的BeanDefinitioncreateBean
:给定一个bean definition,创建一个相应的bean。注意这并不是AutowiredCapableBeanFactory
中的那个createBean
,是自己定义的一个抽象方法。
未完......