Spring源码解析——BeanFactory
本篇文章大量内容来源于官方的代码注释,看起来会比较枯燥,但了解Spring最直接,最正规的方式也就如此了。
庞大的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:
// 返回一个beanName对应的实例,根据bean对应的bean定义的不同,返回的可能是单例的也可能不是。bean定义中描述了该对象是单例还是非单例
Object getBean(String beanName)
// 和上一个一样,不同的是,这有一个`args`参数,这是允许用户使用自己的参数替换bean定义中描述的
Object getBean(String name, Object... args)
// 这一类`getBean`使用类型查找,主要为保证类型安全
<T> T getBean(Class<T> requiredType)
下面的方法不直接创建Bean,而是返回一个ObjectProvider,允许延时按需创建,并且支持存在性和唯一性校验:
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType)
下面是一些其它的基础方法:
// 是否存在对应beanName的bean定义,或者通过外部注册了一个singleton实例?(当我们了解到SingletonBeanRegistry时会详谈)
boolean containsBean(String beanName)
// 该beanName对应的bean是一个共享单例bean吗?换句话说,每次getBean总是返回一个对象吗?
boolean isSingleton(String beanName)
// 该beanName对应的bean是一个独立原型吗?换句话说,每次getBean都是返回一个新创建的对象吗?
boolean isPrototype(String beanName)
// 获取给定beanName的别名
String[] getAlias(String name)
够了,我们不是API文档,所以就介绍这些吧,小总结
- BeanFactory中持有一堆bean定义,它会根据这些定义在你getBean时为你创建bean实例
- BeanFactory接口并未约束如何获取这些bean定义,可能是基于XML,可能是注解,在一些基础的BeanFactory中,甚至暴露了接口让用户自行传入
- BeanFactory中的bean分为单例和原型两种,我个人感觉这里原型这个命名不太妙,虽然原型模式的意思就是给一个对象模板,每次基于模板创建新的对象,但实际上单例也是基于原型模板创建的,只不过需要有东西来负责保存这个Singleton对象,以让第二次getBean时返回这个对象
- BeanFactory也没约束实现类如何保存单例对象
ListableBeanFactory接口
ListableBeanFactory是一种可枚举全部bean实例的Bean工厂,用户无需根据所有名字一个一个的查找
// 获取制定bean定义是否存在,和BeanFactory中的`containsBean`的区别是,它不考虑工厂的层次结构,只返回本工厂中的bean定义
boolean containsBeanDefinition(String beanName)
// 获取bean定义的数量,也是只返回本工厂中的bean定义数量
int getBeanDefinitionCount()
// 获取本工厂中所有bean定义的名字
String[] getBeanDefinitionNames()
接口还提供了一些和注解相关的接口:
// 返回具有指定注解的Bean名列表,通过FactoryBean创建的对象将被初始化以确定类型
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType)
// 返回具有指定注解的Bean,通过FactoryBean创建的对象将被初始化以确定类型
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
// 返回bean指定的注解
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
接口重新定义了几个和BeanProvider相关的接口,都是为其加上了allowEagerInit
参数,这里只列出一个
// ObjectProvider的流式访问是否会初始化lazy-init的单例对象以及通过FactoryBean创建的对象
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit)
HierarchicalBeanFactory
HierarchicalBeanFactory是一种提供层次关系的Bean工厂
// 获取父bean工厂
BeanFactory getParentBeanFactory()
// 本地是否包含指定bean?不考虑祖先工厂
boolean containsLocalBean(String name)
ConfigurableBeanFactory
该接口提供了对Bean工厂的基本设置方法,所有有关BeanFactory的配置设置的方法都在这个接口中。大部分BeanFactory都实现了该接口,但这个接口暴露的方法不应该被应用程序代码使用,它们应该坚持使用BeanFactory
和ListableBeanFactory
中定义的方法,本接口中的方法只应该被框架内部使用。
我这里挑几个我觉得有趣的介绍下:
// 设置bean类的类加载器,默认使用线程上下文加载器
void setBeanClassLoader(ClassLoader beanClassLoader)
// 设置类型转换器,BeanFactory将使用它做bean属性值、构造器参数值等的转换
void setTypeConverter(TypeConverter typeConverter)
// 添加Bean的后处理器,它们将在Bean被该工厂创建时被应用
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
// 注册scope,Spring原生只支持singleton和prototype,这里给了动态定义Scope的能力,我不知道SpringMVC中的request、session等scope是否是使用该方法定义的
void registerScope(String scopeName, Scope scope)
// 考虑一个BeanDefinition在当前工厂和其祖先工厂中都有定义,该方法可以在必要时合并子工厂中的bean定义和夫工厂中的bean定义
BeanDefinition getMergedBeanDefinition(String beanName)
// 用来设置某一个bean当前是否在创建过程中,仅限容器内部使用
void setCurrentlyInCreation(String beanName, boolean inCreation)
// 为给定bean注册一个依赖bean,在给定bean销毁前被销毁
void registerDependentBean(String beanName, String dependentBeanName)
可以看出这个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。
介绍下它的部分方法:
// 创建一个指定类型的第三方bean,执行完整的bean初始化流程,包括所有的BeanPostProcessor、所有标准化Bean回调,填充带注释的属性和方法,不指定是使用哪种注入方式(BY_TYPE、BY_NAME)
<T> T createBean(Class<T> beanClass)
// 填充给定的bean实例,通过后实例化回调以及bean属性的后处理器(比如注解驱动注入)
void autowireBean(Object existingBean)
// 根据bean工厂中beanName对应的bean定义去配置Bean,比如属性等
Object configureBean(Object existingBean, String beanName)
Registry相关接口
AliasRegistry
管理别名的简单接口,是BeanDefinitionRegistry
的父接口。
只有简单的四个方法
Spring beanfactory包下唯一封装了bean定义注册的接口,内容也很简单,是对bean定义的增删改查,所以也没啥可介绍的
SingletonBeanRegistry
提供共享单例bean的管理,可以被BeanFactory实现,以统一的方式暴露单例bean管理功能。
// 使用beanName注册一个单例对象,会假设这个对象已经被完全初始化了,不会执行任何初始化回调和销毁回调
void registerSingleton(String beanName, Object singletonObject)
// 获取一个单例对象,只会返回已有的单例对象,对于singleton的bean定义,不会创建一个单例对象并返回
Object getSingleton(String beanName)
其它的
count
和contains
等方法都是只针对已有的单例对象的,和getSingleton
一样。
DefaultSingletonBeanRegistry实现
DefaultSingletonBeanRegistry
是Spring中用来注册单例Bean实例的核心类,它继承了SimpleAliasRegistry
,所以有开箱即用的别名注册功能,实现了SingletonBeanRegistry
相关接口。
该类在基础的单例注册上提供了很多新功能:
- 支持
DisposalBean
实例的注册,会在注册处shutdown时销毁 - 支持注册bean之间的依赖关系,以强制执行适当的销毁顺序
- 该类不了解有bean定义这个概念,也不了解特定的bean创建流程
属性
// 单例对象的缓存,beanName => 实例
Map<String, Object> singletonObjects
// 单例对象工厂的缓存,beanName => 对应工厂。所以该类是支持通过工厂完成单例bean的懒创建的
Map<String, ObjectFactory<?>> singletonFactories
// 早期单例对象缓存,beanName => 实例。目前尚不明确早期单例对象是啥。gpt给出的解释是,在bean的创建过程中,它们有可能依赖其它bean,导致它们并没有完全初始化完成,该缓存保存的就是这些没有完全初始化完成的bean。一旦它们初始化完成,就被从这个cache移动到`singletonObjects`
Map<String, Object> earlySingletonObjects
// 已注册的单例对象,按照注册顺序排列它们的beanName,是个LinkedHashSet
Set<String> registeredSingletons
// 当前在创建过程中的beanName
Set<String> singletonsCurrentlyInCreation
// 被创建过程检查排除的beanName
Set<String> inCreationCheckExclusions
// DisposableBean缓存,beanName => 实例
Map<String, Object> disposableBeans
// bean之间的包含关系的缓存,包含beanName => 被包含beanName集合
Map<String, Set<String>> containedBeanMap
// bean之间依赖关系的缓存,beanName => 依赖它的beanName集合
Map<String, Set<String>> dependentBeanMap
// bean之间依赖关系的缓存,beanName => 它依赖的beanName集合
Map<String, Set<String>> dependenciesForBeanMap
小总结:从它的属性中我们可以看出,该类并非只是简单实现了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
,是自己定义的一个抽象方法。
getBean
我们先来看看核心的getBean
如何实现,实际上我们已经能推测了,这个方法大概会做如下的事:
- 从单例注册表中查询
- 在本工厂中查找相关的bean定义,若没有,查看父factory中有没有,有就直接利用
- 根据bean definition创建
- 如果父子都有相关的bean定义,还要合并
- 如果是FactoryBean,处理这种情况
从单例表中查询
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 处理别名,解析实际的beanName
String beanName = transformedBeanName(name);
// 用于保存返回的bean实例
Object beanInstance;
// 对于手动注册的那些单例实例,首先检查
Object sharedInstance = getSingleton(beanName);
// 如果找到了,并且调用者没有要求使用特定的args初始化
if (sharedInstance != null && args == null) {
// 该方法用于兼容FactoryBean,如果instance是FactoryBean,该方法会处理
// 如果不是FactoryBean,直接返回原对象,这里我们先不深入它
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// ...省略后面的代码...
}
判断循环引用
else {
// 如果我们已经在创建这个bean实例了,我们可以推测陷入了循环引用
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// ...省略后面的代码...
实际上就是本地的一个表prototypesCurrentlyInCreation
保存了正在创建中的原型对象,查表便知道自己有没有在创建了:
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
自己若没有相关bean定义,去找他爹
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
// 若本工厂没有相关bean定义,并且具有父工厂
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 检查父工厂,找到直接返回退出
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
标记bean已经创建过
// typeCheckOnly是用户传入的,代表获取该bean只是为了做类型检查,而不是实际使用
// 如果需要实际使用的话,这里会标记bean已经创建过了
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// 清除mergedBean缓存
clearMergedBeanDefinition(beanName);
// 添加到表中
this.alreadyCreated.add(beanName);
}
}
}
}
合并bean定义,依赖bean先行初始化,解循环依赖
try {
// 如果当前父工厂也有相应的bean定义,和父工厂的合并并检查
// 合并后的mergedBeanDefinition会存在于mergedBeanDefinitions缓存中
// 以避免每次再创建都要合并一次,后续直接使用缓存即可
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保当前Bean依赖的Bean先初始化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 检测循环引用,即当前bean依赖dep,而dep又依赖当前bean
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖关系,这个来自于ConfigurableBeanFactory接口
registerDependentBean(dep, beanName);
try {
// 初始化依赖bean先
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
如果是单例bean,使用单例注册表的ObjectFactory接口来创建该bean
if (mbd.isSingleton()) {
// getSingleton并提供ObjectFactory,此时会在该beanName没在注册表中
// 时调用ObjectFactory创建该bean,并放到注册表中
sharedInstance = getSingleton(beanName, () -> {
try {
// createBean,由子类实现,抽象Bean工厂不关心,只提供模板逻辑
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 处理FactoryBean情况
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
如果是prototype,创建对象,并在过程中写入prototypeInCreation表
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
beforePrototypeCreation
方法就是操作prototypesCurrentlyInCreation
表,该表实际上是一个ThreadLocal
,会记录当前线程下所有正在创建的prototype beanName,若一个prototype在创建前查表发现表中包含自己,证明出现了从自己到自己的循环引用:
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
// 写入表
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName);
}
// 如果已经存在,并且尚为字符串,转换成为集合再存
else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
// 否则,已经是集合,直接塞
else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
afterPrototypeCreation
我就不放出来了,就是移除表元素
处理其它Scope的情况*
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
应用TypeConverter
当你要获取一个bean时,你指定了类型,但实际bean的类型却并不是你指定的,此时Spring会检测你有没有设置对应的TypeConverter
,如果有,在doGetBean
的最后,它将尝试进行一次类型转换:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 省略前面的代码
return adaptBeanInstance(name, beanInstance, requiredType);
}
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
// 如果用户设置了预期类型,并且和bean不符
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// convert
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
总结
我们了解了 AbstractBeanFactory
中 getBean
的流程
- 先尝试有没有手动注册的singleton,如果有(并且没有指定args)则直接使用
- 若拿到的
beanInstance
是FactoryBean,处理
- 若拿到的
- 否则,查看本工厂有没有相关的bean定义,如果没有,而且存在父工厂,委托父工厂
getBean
- 如果有,先判断当前执行栈中是否有同名的prototypeBean正在创建,通过ThreadLocal确保是当前执行栈,如果有,出现循环引用
- 尝试和父工厂的bean定义合并,并添加到缓存
- 从bean定义中发现当前bean依赖的bean,注册引用关系,并先初始化依赖bean。此时能发现循环依赖关系。
- 查看是否是单例,如果是,调用
createBean
创建并放到bean注册处- create出的bean会看看是否是FactoryBean,是就处理
- 如果是prototype,调用
createBean
创建并在创建过程中维护同名表的正确性- create出的bean会看看是否是FactoryBean,是就处理
- 否则,是自定义scope,处理
- 如需类型转换,应用TypeConverter
createBean
的策略我们暂且不知道,那是由子类实现的。实际上,在上面获取bean定义时,我们忽略了getMergedLocalBeanDefinition
的细节,该方法内部是调用了getBeanDefinition
这个抽象方法的,这意味着对于如何创建bean,以及如何获得bean定义(比如基于xml还是注解),这些都是具体的子类维护的。
BeanPostProcessorList
AbstractBeanFactory
实际上还定义了BeanPostProcessor
的缓存列表,但其内部并未应用任何后处理器,这些都是交给子类做的,它只替子类维护一个列表。实际上我怎么感觉这个列表也不应该在这维护呢。。。
AbstractBeanFactory
维护了两个和后处理器相关的属性:
// 后处理器的列表,继承自CopyOnWriteList,保证线程安全性
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();
// 预过滤后处理器缓存,即那些实例化后处理器、销毁后处理器等
@Nullable
private volatile BeanPostProcessorCache beanPostProcessorCache;
相关方法:
// 添加后处理器
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
public void addBeanPostProcessors(Collection<? extends BeanPostProcessor> beanPostProcessors);
// 获取后处理器数量
public int getBeanPostProcessorCount();
// 获取全部后处理器
public List<BeanPostProcessor> getBeanPostProcessors();
// 获取全部预过滤后处理器的内部缓存
BeanPostProcessorCache getBeanPostProcessorCache();
BeanDefinition家族
在这里突然插一下,我们应该介绍下BeanDefinition了。
代码中常见的RootBeanDefinition的继承结构是什么样的呢?
主要有三种角色:
AttributeAccessor
:一个定义了向任意对象添加或访问元数据的通用约定的接口,定义了setAttribute、getAttribute
、removeAttribute
等接口BeanMetadataElement
:不到是干啥的BeanDefinition
:一个BeanDefinition描述了一个Bean实例,其中包含scope信息、类名、是否lazy-init、依赖信息、属性值、构造器参数值以及由具体实现提供的进一步信息等
BeanDefinition接口
// 设置scope
void setScope(@Nullable String scope);
// 设置bean是否懒加载,如果是false,则bean factory初始化时就应该执行该Bean的加载
void setLazyInit(boolean lazyInit);
// 设置该bean被初始化时依赖的bean name,factory应该确保这些bean先被初始化
void setDependsOn(@Nullable String... dependsOn);
// 设置该bean是否是会被自动注入到其它bean中的候选bean
// 该flag只影响by type的自动注入,对于显式的通过bean名的引用无效
void setAutowireCandidate(boolean autowireCandidate);
// 多个bean作为候选时,是否选择该bean
void setPrimary(boolean primary);
// 指定使用哪个factory bean
void setFactoryBeanName(@Nullable String factoryBeanName);
// 指定使用factory bean的哪个方法
void setFactoryMethodName(@Nullable String factoryMethodName);
// 获取构造器参数值。返回的实例可能会再bean factory的后处理期间被修改
ConstructorArgumentValues getConstructorArgumentValues();
// 返回应用到bean的新实例上的属性值。再bean factory的后处理期间被修改
MutablePropertyValues getPropertyValues();
// 设置初始化方法名
void setInitMethodName(@Nullable String initMethodName);
// 设置destroy方法名
void setDestroyMethodName(@Nullable String destroyMethodName);
// 返回该bean定义的一个可解析的类型,基于bean的类型或特定的元数据
ResolvableType getResolvableType();
// 是否singleton
boolean isSingleton();
// 是否prototype
boolean isPrototype();
// bean是否是抽象的,即不需要初始化
boolean isAbstract();
// 返回该bean definition来源的描述(为了在错误发生时展示上下文)
String getResourceDescription();
// 返回原始bean定义,貌似bean定义是可以被包装的
BeanDefinition getOriginatingBeanDefinition();
AbstractBeanDefinition
是任何具体的、成熟的BeanDefinition类的基类,分解出GenericBeanDefinition
、RootBeanDefinition
以及ChildBeanDefinition
的常见属性。
提供五种自动装配常量,对应AutowireCapableBeanFactory
接口定义的五种
AUTOWIRE_NO
:完全没有外部的自动注入AUTOWIRE_BY_NAME
:通过bean名自动注入bean属性AUTOWIRE_BY_TYPE
:通过类型自动注入bean属性AUTOWIRE_CONSTRUCTOR
:自动注入构造器AUTOWIRE_AUTODETECT
:自动决定使用何种策略,已经在Spring3.0废弃
提供四种依赖检查常量:
DEPENDENCY_CHECK_NONE
:完全没有依赖检查DEPENDENCY_CHECK_OBJECTS
:对于对象引用进行依赖检查DEPENDENCY_CHECK_SIMPLE
:对于简单属性进行依赖检查DEPENDENCY_CHECK_ALL
:对于对象引用以及简单属性,都进行依赖检查
还提供了一些其它属性,我们可以推测它带有的功能:
Map<String, AutowireCandidateQualifier> qualifiers
:用来支持多个匹配bean时进一步过滤,思考@Qualifier
boolean nonPublicAccessAllowed
:是否允许非公有方法和属性的访问?boolean lenientConstructorResolution
:宽松的构造器解析?MethodOverrides methodOverrides
:方法重载?记录IOC容器在运行时将重载bean的哪些方法?
RootBeanDefinition
暂时略过
AbstractAutowireCapableBeanFactory
一个实现了默认bean创建流程的BeanFactory模板类,实现了RootBeanDefinition
类定义的全部功能,实现了AutowireCapableBeanFactory
接口以及AbstractBeanFactory
定义的createBean
。
提供Bean创建(构造方法解析)、属性填充、装配(包括自动装配)以及初始化,支持构造器的自动装配,以及属性的自动装配(by name以及by type)。
子类需要提供resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
方法的实现,该方法会被基于类型的自动装配使用。
本类不假定也不实现bean定义的注册能力。
属性分析
// 实例化Bean实例的策略,有两个子类
// - SimpleInstatiationStrategy:通过反射达到的简单实例化策略,不支持方法注入,但给子类提供了要重写的hook以添加方法注入支持
// - CglibSubclassingInstantiationStrategy:BeanFactory默认使用的策略。如果方法需要被容器重写以完成方法注入,该策略可以通过CGLIB动态生成子类来实现
// 关于方法注入的相关文档:https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-method-injection.html
private InstantiationStrategy instantiationStrategy;
// 方法参数名解析策略,比如构造器方法参数名
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
// 是否自动尝试解决bean之间的循环引用
// 注意循环引用解析代表着有一个bean将会收到另一个未完全初始化的bean的引用,这可能在初始化阶段导致细微(或许没那么细微)的副作用
// 但大多数场景下都是正常工作的。该值默认为true,若关闭该选项,则会在遇到循环引用时抛出一个异常
// 不建议依赖bean间的循环引用,当两个bean循环引用时,可以重构程序逻辑,用第三个bean封装二者的通用逻辑
private boolean allowCircularReferences = true;
// 在循环引用的情况下,是否通过注入一个裸bean实例来解决,尽管这个Bean最终可能会被包装(比如通过AOP自动代理)
// 仅会在循环引用解决最终无法被解决时使用,整个bean注入的过程失败后才会注入裸对象
// 默认是false
private boolean allowRawInjectionDespiteWrapping = false;
// 在自动注入过程中会被忽略的类型,比如String
private final Set<Class<?>> ignoredDependencyTypes = new HashSet<>();
// 在自动注入过程中会被忽略的接口类型,默认只有BeanFactoryAware接口被忽略
private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();
// 当前正在创建的Bean名字,看起来也是用于解决循环引用的,也是ThreadLocal
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
// 尚未完成的FactoryBean实例的缓存:FactoryBean名 => BeanWrapper
private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();
// 每个工厂类的候选工厂方法缓存
private final ConcurrentMap<Class<?>, Method[]> factoryMethodCandidateCache = new ConcurrentHashMap<>();
// 被过滤的PropertyDescriptor的缓存:bean类型 => PropertyDescriptor数组
private final ConcurrentMap<Class<?>, PropertyDescriptor[]> filteredPropertyDescriptorsCache =
new ConcurrentHashMap<>();
构造器
public AbstractAutowireCapableBeanFactory() {
super();
// 忽略BeanNameAware、BeanFactoryAware、BeanClassLoaderAware这三个接口的依赖检查?
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
if (NativeDetector.inNativeImage()) {
this.instantiationStrategy = new SimpleInstantiationStrategy();
}
else {
this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
}
}
public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
this();
setParentBeanFactory(parentBeanFactory);
}
方法
createBean:
还记得AutowireCapableBeanFactory
中的createBean
接口吗?它的功能是创建一个第三方Bean,执行完整的Bean初始化流程,包括BeanPostProcessor的执行、标准化Bean回调、填充属性和方法,但该Bean的Bean Definition不会进入BeanFactory中,BeanFactory也不会纳管这个Bean。
@Override
public <T> T createBean(Class<T> beanClass) throws BeansException {
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
return (T) createBean(beanClass.getName(), bd, null);
}
这个接口调用了AbstractBeanFactory
中定义的createBean
!哦!原来这个抽象方法的bean定义是外部传递的,外部通过beanName解析出bean定义后传入这里直接使用,这让getBean
以及来自AutowireCapableBeanFactory
两个接口能够复用一个createBean
。
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// 确保bean的类在此时已经被实际解析了,并在动态解析无法被保存在共享mbd中的class的情况下克隆bean定义
// 上面这一句是官方的注释,我们看不懂,先不管,等研究resolveBeanClass时再考虑
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 准备方法重载,这里我们也先不管
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 给BeanPostProcessor一个机会去返回一个代理来代替目标Bean实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 创建Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
实际上我们目前关心的只有两个方法调用,一个是resolveBeforeInstantiation
,一个是doCreateBean
对于第一个,我大概可以猜出它就是去应用所有的InstantiationAwareBeanPostProcessor
的before后处理器,若其中任意一个返回了一个对象,就直接终止bean创建过程,使用该对象。
而第二个,我大概可以猜出是走常规的Bean创建流程,走所有的属性注入、bean后处理器调用、初始化方法调用等。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 确保bean类在此刻已经实际地被解析了
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 找类
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 应用InstantiationAwareBeanPostProcessor的before方法,若返回了一个bean,应用实例化后方法(注意这里是实例化后方法)
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 若before方法已经被调用,并且返回了一个对象替代对应的bean,记录下。默认情况下该Boolean为null
// 反正只要不为false就都能进入,若为false下次就不用尝试了,反正before不会返回啥的
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
这里有道面试题,就是SpringBean的生命周期,这里实际上是实例化阶段,覆盖了实例化阶段前后的
InstantiationAwareBeanPostProcessor
的后处理方法。
下面就是doCreateBean
,这是实际创建Bean的方法,在此处InstantiationAwareBeanPostProcessor
的before后处理器已经调用过了。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 如果是单例,先去factoryBeanInstanceCache里查一圈
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 如果刚刚没查或者没查着,创建Bean实例
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 省略......
}
嘶,BeanWrapper
是什么!?
BeanWrapper是Spring的底层JavaBean基础设施的核心接口,通常不会直接使用,但会因为DataBinder和BeanFactory而间接使用。
提供获取和设置属性值的能力、获取属性描述符以及查询属性的可读性、可写性,其核心接口有如下几个:
Object getWrappedInstance()
:获取被包装的对象Class<?> getWrappedClass()
:获取被包装的bean的类型PropertyDescriptor[] getPropertyDescriptor()
:获取全部属性描述符PropertyDescriptor getPropertyDescritor(String beanName)
:获取单个属性的属性描述符总之,这东西就是使用JavaBean标准,你可以通过这东西访问、设置JavaBean的属性值,也就是set和get方法的调用。Spring BeanFactory中的Bean都使用它来包装。
继续往下走,这里实际上一坨代码,但就是调用mbd的BeanDefinitionPostProcessor,貌似这里还允许在属性填充前对mbd进行二次修改:
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 允许后处理器去修改合并的mbd
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
继续继续:
// 若该方法是由外部getBean调用的,并且mbd是singleton,还不是手动注册的
// 那么AbstractBeanFactory会调用`DefaultSingletonRegistry`的getSingleton,
// 并传入一个回调,那个方法会先将当前bean设置成currentlyInCreation的,然后再调用
// 回调,回调会调用createBean创建Bean对象。
//
// 这时,我们会向SingletonRegistry中添加一个SingletonFactory,在该bean创建期间
// 若出现循环引用(该bean被其它bean依赖,会在填充属性时发生循环引用),就通过SingletonFactory
// 工厂方法返回一个早期引用。当然,这得是允许循环引用开着的情况下
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
继续继续,我们进入了初始化阶段:
Object exposedObject = bean;
try {
// 填充bean属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean(估计是调用BeanPostProcessor)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
初始化阶段主要是填充了bean的属性,又调用了一下initializeBean
,这些方法我们后面会一个一个看的。
// 如果之前暴露了早期singleton实例
if (earlySingletonExposure) {
// 获取早期暴露出去的singleton引用
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 如果在初始化后exposedObject仍等于原始的bean时(没有发生AOP包装?)
if (exposedObject == bean) {
// 就让exposedObject等于早期singleton引用
exposedObject = earlySingletonReference;
}
// bean已经被包装了,若不允许在bean被包装的情况下仍然使用裸注入
// 并且有被其它bean依赖
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 获取依赖它的bean
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 如果移除失败(该bean可能并非只用于类型检查,是要被实际使用的bean)
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
// 添加到set中
actualDependentBeans.add(dependentBean);
}
}
// 如果set不为空,报错,出现循环引用
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
这段代码主要是为了allowRawInjectionDespiteWrapping
服务的,会获取所有依赖该bean的bean,它们现在内部注入的是早期的,还未填充属性、未初始化的bean,而当初始化阶段结束后,由于BeanPostProcessor的执行,这个早期bean有可能已经被AOP包装过了,但这些依赖它的依赖的还是原始的早期bean,此时若allowRawInjectionDespiteWrapping
未false,就是不允许这种情况发生,直接报错。
最后一段:
// 如果有必要的话,将bean注册为disposable bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 返回最终的对象
return exposedObject;
做个小总结的话就是:
- 首先如果是单例的话,会先看factoryBeanInstanceCache中是不是已经有了,如果有了直接拿
- 如果第一步没拿到对象,可能不是单例,或者没创建过,就走
createBeanInstance
去创建 - 然后会调用一个mbd的BeanDefinitionPostProcessor,允许在填充属性前对mbd做二次修改
- 然后如果是singleton的话,通过注册SingletonFactory让外部在循环引用时可以拿到该bean的早期引用。早期引用不一定是最后的引用,因为可能存在AOP包装
- 然后就是执行填充属性
- 执行bean post processor,这个过程中可能会有后处理器返回新的对象作为最后的bean,典型的例子就是AOP,它会包装该对象,返回一个代理对象
- 最后一步就是一个校验,因为如果有循环引用的话,并且有bean post processor返回了新引用,那么那些注入到循环引用中的早期对象就已经不是最后bean factory暴露出去的对象了,此时可能会产生大问题,如果不允许这种情况发生,就直接抛异常
下面我们对之前doCreateBean
中忽略的那些关键方法做一个了解
思考:为什么这个类不关心Prototype情况下的循环引用呢?
因为在
AbstractBeanFactory
的getBean
中已经解决了,直接抛出异常,不允许Prototype循环引用。
createBeanInstance
这个方法是实际创建Bean实例的,它会尝试使用几种策略去创建:factory method、构造器自动装配或简单实例化
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 确保bean的Class已经正确解析了
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 如果mbd有提供InstanceSupplier,就使用这个
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果mbd有提供工厂方法,使用工厂方法
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 如果重复初始化一个bean,那么使用快捷方式,它的构造器或factory method已经被解析过了
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// mbd的该属性缓存了已经被解析的构造器或factory method
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// mbd的该属性标记构造方法参数已经被解析了
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// 获取候选构造器,这里是从SmartInstantiationAwareBeanPostProcessor中获取
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 若ctors获取成功,或者mbd的autowire模式是构造器注入,或者mbd具有构造器属性值,或者外界传入的args不为空
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 上一步没成功,选择mbd中偏向的构造器,这里不会注入外界传入的args
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 没有特殊处理,使用无参构造器
return instantiateBean(beanName, mbd);
}
看看autowireConstructor
。这个方法是根据构造器参数类型来进行自动装配的,可以显式的指定构造参数值,剩下的就使用bean工厂中的bean进行装配。
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
需要说一下的就是这个explicitArgs
,它是可以被外部的getBean
传入的属性值,如果没传入(null),就暗示着使用bean definition中定义的构造器参数值
我们暂时不深入ConstructorResolver
,总之就知道它是根据传入的内容自动解析对应的构造器,并进行构造函数调用、传入对应参数最后得到创建的对象的BeanWrapper
就好。
而instantiateBean
方法则是使用默认构造器去实例化对象,这就不涉及到参数了。如下,我省略了一些代码,简单来说就是使用类中的实例化策略去实例化对象,并使用BeanWrapperImpl包装:
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
Object beanInstance;
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
// 设置类型转换服务、注册自定义属性编辑器
protected void initBeanWrapper(BeanWrapper bw) {
bw.setConversionService(getConversionService());
registerCustomEditors(bw);
}
小总结:
createBeanInstance
会根据传入的mbd、args来尝试使用多种方法实例化Bean对象- 它会参考mbd中的构造器属性、会参考
getBean
中编程式传入的args - mbd中有关于解析对应构造器和参数的缓存,下次再创建不用重复解析
这里的自动装配不是你理解的
@Autowired
,想象你用xml定义了一些bean,你描述了构造方法参数名和对应的参数值,然后xml会被解析成BeanDefinition对象,BeanDefinition中就包含了这些构造函数参数信息,而这里的自动装配就是将这些信息传递到构造函数参数中,并完成bean实例的创建。
populateBean
使用bean definition中的property values装载在给定BeanWrapper中的bean实例。
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// null instance的处理
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// 给任何的InstantiationAwareBeanPostProcessor一个在属性被设置之前去修改bean状态的机会
// 如果不是合成bean,并且具有实例化后处理器,调用其after方法
// 因为实例化后处理器中若返回了一个代理对象,则不会进入populateBean,上面的代码会主动调用after后处理方法
// 但若没返回代理对象,则后处理方法也没被执行,会在populateBean的开始处执行
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 如果after后处理器返回false,则停止下面的流程,不会填充属性
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
// 下面就是byName和byType注入
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
// 如果有实例化Aware后处理器,还需要在属性设置后调用它们的postProcessPropertyValues方法
// 注释里说这个后处理方法是在工厂将给定的pvs应用到给定bean之前时,允许检查是否所有的依赖都被满足,
// 比如在bean的属性setter上有一个Required注解。也就是说允许高层通过提供后处理器并在这个方法中做属性依赖检查
// 也允许替换要apply的属性值,通常基于原始的pvs创建一个新的MutablePropertyValues实例,添加或移除特定属性
// 该方法返回null也会跳过属性populate阶段
// 所以我们可以猜想,上面两个autowire方法实际上还没有把属性真正注入,只是填充了一下newPvs?
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
// 过滤那些需要依赖检查的属性
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 调用后处理器
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
// 如果null skip populateBean
if (pvsToUse == null) {
return;
}
}
// pvs现在是新的了
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 依赖检查
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
// 应用pvs
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
autowireByName
这个方法的作用是对于那些没有被设置的属性,如果它是工厂中其它bean的引用的话就使用它们填充,不过byName需要bean名和对应的属性名匹配
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取所有未满足的非简单属性
// 实际上就是获取所有bw中的属性描述符,对于mbd中的pvs里没有的那些,若是非简单属性,并且有write方法,没被依赖检查排除,就会返回
// 简单属性指的是一个属性的类型属于简单类型,或者是简单类型的数组
// 简单类型包括:Void、原生类型包装类、Enum、CharSequence及其子类、Number及其子类、Date、Temporal、URI、URL、Locale、Class
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
// 对于每一个属性名,若包含和名字相同的bean,就getBean,放到pvs中,并注册dependent表
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
autowireByType
和autowireByName
一样,只不过是通过类型来注入那些未满足的属性的,默认情况下,属性必须有且只有一个match的bean在工厂中。
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
// 哦?bw本身也是TypeConverter?
converter = bw;
}
// 这是要注入的bean名
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// 永远不要尝试通过类型自动装配Object类型,这没意义,即使技术上它是一个未满足的、非简单属性
if (Object.class != pd.getPropertyType()) {
// 获取该属性write方法的参数,也就是我们熟知的setter参数
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
// 初始化被注入属性的依赖描述符
// 依赖描述符是一个要被注入的依赖的描述符,它可以包装一个构造器参数、方法参数或一个属性,允许对它们的元数据进行统一访问
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 调用子类实现的resolveDependency来获取要被注入的参数,添加到pvs中
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
// 所以autowiredBeanNames好像是一个候选bean数组?它是由子类填充的所以目前我们还不知道,不过可以肯定的是每一个属性获取完它都会被清空
// 也就是只包含当前属性的
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
这里要注意的是
resolveDependency
由子类实现,也就是autowireByType
如何选择bean注入这个属性是由子类定义的
checkDependency
执行一次依赖检查,是否所有向外暴露的(具有write方法的)属性都已经被注入了?此次检查可以是object模式、simple模式或all模式或none:
protected void checkDependencies(
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, @Nullable PropertyValues pvs)
throws UnsatisfiedDependencyException {
// 获取依赖检查模式
int dependencyCheck = mbd.getDependencyCheck();
// 获取所有属性
for (PropertyDescriptor pd : pds) {
// 如果具有write方法,并且pvs中不存在对应属性
if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
// 如果是all检查,直接未满足
// 如果是simple检查,若该属性是simple的,未满足
// 如果是object检查,若该属性不是simple的,未满足
boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) ||
(isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
(!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
if (unsatisfied) {
// 抛出异常
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
"Set this property value or disable dependency checking for this bean.");
}
}
}
}
applyPropertyValues
这里我们先略过,它涉及一堆TypeConverter的应用,并且TypeConverter还有缓存,比较麻烦,这里我们只先理解核心原理,就可以理解为将pvs中的属性应用给创建出的实例了即可。
populateBean小总结:
- 首先若存在
InstantiationAwareBeanPostProcessor
,调用after
后处理器,若返回false,则不执行后面的populateBean - 然后按照mbd中的设定,执行autowireByName或ByType
- ByName很简单,因为是一对一注入,ByType较为复杂,实际的解析依赖还是子类的
resolveDependency
实现的 - autowire只会将未满足的非简单属性,从工厂中挑一个bean,但此时不会实际注入到对象中,只是放到了一个mpvs中
- 然后调用
InstantiationAwareBeanPostProcessor
的属性设置后处理器,允许它添加或移除一些属性,对属性做一些检查,返回替换的pvs。也允许返回null终止populateBean阶段 - 然后进行依赖检查,根据mbd中的DependencyCheckType来检查,支持none、simple、object和all
- 然后apply,将mpvs中的属性真正注入到bean实例中,此时和第三部貌似都会应用TypeConverter
initializeBean
初始化Bean,这个很简单,纯过程式的代码:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 调用Aware方法,这里的是部分在初始化时执行的Aware,其它高级Aware可能是通过BeanPostProcessor实现的
invokeAwareMethods(beanName, bean);
// 调用BeanPostProcessor的before方法,这里允许向上层返回一个包装过的wrappedBean,这也是AOP实现的基本原理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 调用after后处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
DefaultListableBeanFactory
上面了解了很多BeanFactory,它们基于BeanDefinition来创建Bean实例、解析依赖、自动装配,但它们都没有定义如何注册一个BeanDefinition。它们都只是用来提供一些公共逻辑,并不能被使用。
DefaultListableBeanFactory
是Spring框架的核心接口,也是实现众多ApplicationContext
的基石,它实现了ConfigurableListableBeanFactory
以及BeanDefinitionRegistry
,这让用户可以对它内部的bean进行迭代,以及注册bean definition。
该类常见的用法是,在访问bean之前,首先注册所有的bean definition(可能是从一个bean定义文件中读取)。而定义了如何读取bean definition的reader通常不是BeanFactory实现的,它们实现自BeanDefinitionReader
。这让它不与对应的BeanFactory耦合。
如何存储BeanDefinition
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// validate校验
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 是否该beanName已经定义过bean definition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 如果不允许bean定义覆盖的话,抛异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// put
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 是否工厂已经进入bean创建阶段了(是否已经有创建好的bean了)
if (hasBeanCreationStarted()) {
// 这里用了一个写时复制技术来拷贝`this.beanDefinitionNames`
// 因为外界可能已经在迭代该工厂中的bean了,为了它们的迭代稳定不修改原来的列表
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 移除手动注册的singleton
removeManualSingletonName(beanName);
}
}
else {
// 此时仍在启动时注册的阶段
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 如果发生了bean定义覆盖,或者在注册时已经存在相关的singleton了,需要resetBeanDefinition
if (existingDefinition != null || containsSingleton(beanName)) {
// 1. 清除和该bean相关的所有mbd缓存
// 2. 销毁和该bean名字一致的singleton
// 3. 通知所有MergedBeanDefinition后处理器reset该beanName
// 4. 对于该工厂中所有父bean是beanName的,递归执行resetBeanDefinition
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
这里我们可以发现,这个factory将自己的生命周期分为两个阶段,第一个阶段是bean定义的注册阶段,第二阶段是已经向外提供工作了的创建阶段。
该工厂使用一个beanDefinitionMap
来存放beanName和对应的BeanDefinition对象的关系。
BeanFactory剩余方法的实现
之前我们研究的那些抽象BeanFactory,它们都实现了byName的getBean
,但没有实现byType的getBean
,这个行为在本类实现。
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return (T) resolved;
}
@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
// 调用resovleNameBean,传入类型、创建参数等解析出一个Bean,如果有,就返回
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
// 没有,去父工厂找
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
}
else if (parent != null) {
ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
if (args != null) {
return parentProvider.getObject(args);
}
else {
return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
}
}
return null;
}
private <T> NamedBeanHolder<T> resolveNamedBean(
ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
// 获取所有候选
String[] candidateNames = getBeanNamesForType(requiredType);
// 当候选数量大于1时,手动注册单例和autowireCandidate优先
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
for (String beanName : candidateNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = StringUtils.toStringArray(autowireCandidates);
}
}
// 最后的候选名称等于1,直接解决了
if (candidateNames.length == 1) {
return resolveNamedBean(candidateNames[0], requiredType, args);
}
else if (candidateNames.length > 1) {
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
// singleton,直接将bean实例放入,否则放入其类型
for (String beanName : candidateNames) {
if (containsSingleton(beanName) && args == null) {
Object beanInstance = getBean(beanName);
candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
candidates.put(beanName, getType(beanName));
}
}
// 解析主要候选,即那些bean definition的isPrimary返回true的,这里还涉及到多个Primary时的报错
String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
// 如果没有primary的bean定义,解析最高优先级的
// 这里Spring通过OrderComparator类来实现给定bean的优先级获取以及优先级之间的比较
// AnnotationAwareOrderComparator实现了基于`@Order`或`@Priority`注解的优先级定义
if (candidateName == null) {
candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
}
// 如果找到了,从map中根据候选名字查找,此时有可能查到实例,也有可能查到类型,查到类型就resolve
if (candidateName != null) {
Object beanInstance = candidates.get(candidateName);
if (beanInstance == null) {
return null;
}
if (beanInstance instanceof Class) {
return resolveNamedBean(candidateName, requiredType, args);
}
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
}
// 如果在nonUniqueAsNull == true的情况下,非唯一时返回null,否则,抛出异常
if (!nonUniqueAsNull) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
}
return null;
}
而resolveNamedBean
很简单,既然已经拿到beanName
了,就直接委托父类getBean
就好了
private <T> NamedBeanHolder<T> resolveNamedBean(
String beanName, ResolvableType requiredType, @Nullable Object[] args) throws BeansException {
Object bean = getBean(beanName, null, args);
if (bean instanceof NullBean) {
return null;
}
return new NamedBeanHolder<T>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
}
看到这里,我们知道了DefaultListableBeanFactory
实现了byType的getBean
,并且在多个候选时,它会尝试根据primary
来获取主候选,如果不成功,会根据优先级来获取。
resolveDependency
这个也是一个父类留下的大坑,在父类的autowireByType
中,把根据类型、converter等来获取实际要注入的bean的功能交给子类实现了,而这个子类要实现的方法就是resolveDependency
。
你可以大体上理解为是下面这个场景,不过BeanFactory并不假设Bean之间依赖的定义方式s:
public class BeanA {
@Autowired
private BeanB beanB;
}
BeanA中依赖BeanB,但是通过类型来注入的,若有很多个BeanB类型或其子类都注册到factory,我们要解析出其中的一个,或者摆烂,抛个异常说我们不知道帮你注入哪个。
// 再次说明,DependencyDescriptor描述了依赖要注入的位置以及依赖类型,要注入的位置可能是一个方法参数
// 构造函数参数或一个属性。它提供了一个统一的方式来访问这些东西以忽略具体的注入点细节
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 初始化方法参数发现器,因为descriptor描述的可能是方法或构造器,传入的发现器会在调用`getDependencyName`时
// 若需要解析方法的参数名时,进行参数名解析
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 省略了一些我们不关心的分支...
// 可以看出实际的解析工作来自于AutowireCandidateResolver,并且这东西还支持在必要时才进行解析的懒解析方式
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
// 如果通过上一个方式获取失败,调用`doResolveDependency`
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
我们看到这里进行解析时实际上依赖了Spring中的另一个组件——AutowireCandidateResolver
来解析自动装配候选。实际上@Qualifier
以及@Lazy
注解就是用这个东西实现的。而在它选不出来时,该factory实际上也会去调用自己的doResolveDependency
方法去尝试解析出一个依赖(比如没定义@Qualifer
和@Lazy
等)
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 这是一个允许在真正的type matching算法执行前返回预先定义好的数据以加快性能的快捷方式,目前只有基于`@Autowired`注解的这种方式使用了这个捷径,后面应该会谈到
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
// 对于给定依赖,是否有一个默认值是建议被返回的?
// QualifierAnnotationAutowireCandidateResolver实现了该方法,它查找`@Value`注解,并返回其中定义的内容
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
// 字符串,有可能是el表达式,尝试解析并设置
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
// 如果需要类型转换,可以应用类型转换器,将得到的类型转换成依赖中需要的类型
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// 自定义的TypeConverter可能不支持TypeDescriptor的解析......
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 没有suggestedValue,对于用户可以理解为没有`@Value`注解
// 这里就不再依赖AutowireCandidateResolver了,自己解析
// multipleBeans是用来解析依赖类型是数组、集合、Map等的,这里我们忽略掉吧。我这里感觉是如果你依赖的类型是`List<BeanA>`,这里就会把所有BeanA给找出来并成为一个List注入进去
// 但这只是我的臆想。总之,在依赖类型不是那些聚合类型时,该方法直接返回null。
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// multipleBeans解析失败,这里获取自动注入候选
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 为空,并且是Required,抛异常,不是Required返回null就好了
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 候选大于1
if (matchingBeans.size() > 1) {
// 老熟人了,在getBean的byType版时也出现过,完成@Primary和@Order、@Priority的解析
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
// 如果没法选出一个,并且还是Required,尝试让DependencyDescriptor选一个
// 不是Required直接返回null
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
// 选出了候选
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// 只有唯一候选
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 如果选出的候选是一个类型,不是实例的话,还需要解析类型
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
// nullbean的解析
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
小总结:
- 在进行byType的autowire时,首先会让
AutowireCandidateResovler
来进行解析 AutowireCandidateResovler
会完成@Qualifier
和@Lazy
的功能- 若它解析不出来,则问
AutowireCandidateResovler
要一个建议值,此时会进行@Value
的解析 @Value
的解析会经过TypeConverter
转换,以在找到的类型和依赖不兼容时进行转换(如果定义了对应的转换器的话)- 若
@Value
解析出字符串,还要进行el表达式的解析 - 都解析不出来,将尝试自己从bean factory中获取
- 当有多个,尝试解析
@Primary
和@Order
、@Priority
- 如果还是不能唯一确定一个就让
DependencyDescriptor
选一个
BeanFactory总结,知识串联
从getBean
开始
我们有这么一个简单的Bean:
public class Person {
private String name;
public Person() {}
public Person(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
有这样一串代码,创建乐一个DefaultListableBeanFactory
,初始化一个rbd,设置属性值,并向工厂注册这个rbd,最后,我们通过工厂的getBean
来获取注册的bean:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
rbd.setBeanClass(Person.class);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("name", "yudoge");
rbd.setPropertyValues(pvs);
factory.registerBeanDefinition("myPerson", rbd);
Person person = (Person) factory.getBean("myPerson");
System.out.println(person);
结果显然是预期的,但我们从这个getBean
开始,梳理整个bean factory体系的执行流程
首先,getBean
是由AbstractBeanFactory
提供的,我们调用的这个只有name
参数:
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
在doGetBean
,中会经历如下过程:
- 是否已经有缓存的singleton了,显然没有,而且我们是prototype
- prototype是否在创建过程中,换句话说是否产生了循环引用?显然没有
- 如果本工厂不包含该bean的definition,委托父工厂getBean,显然我们包含
- 和父工厂合并得到mbd,显然合并后还是我
- 遍历mbd中的dependsOn,发现循环引用,注册dependents关系,先对依赖bean做
getBean
确保它已经被初始化(这只能检测到直接循环引用,A引用B,B引用A) - 判断mbd是否是singleton,是的话调用createBean创建并缓存到
DefaultSingletonRegistry
- 是否是prototype,是的话createBean创建,在创建过程中将它添加到
isPrototypeInCreation
表中,它是个ThreadLocal
的表,用于检测Prototype的循环引用
注意,这里singleton的循环引用并没有完全解决,只解决了prototype的
createBean
是子类AbstractAutowireCapableBeanFactory
提供的,创建bean过程很复杂,涉及调用正确的构造函数初始化、填充pvs中的属性、自动装配属性、后处理器的调用、aware接口方法的调用等等,过程如下:
- 调用所有的实例化Aware后处理器的before方法,若返回一个对象则认为对象创建被它接管了,直接应用
实例化
后的后处理器,否则,无事发生 - 如果mbd是singleton,从内部的
factoryBeanInstanceCache
缓存拿singleton对象,拿到了就不用创建了,否则要走创建过程 - 创建过程会选择合适的构造器实例化Bean,这里可以通过设置mbd的AutowireMode来走构造函数自动装配,我们这里走的是默认构造器
- 然后就要判断mbd如果是singleton,并且允许循环引用,就将未创建完成的早期singleton通过
DefaultSingletonFactory
中addSingletonFactory
的方式暴露出去,允许其它bean注入该singleton的早期对象(父类getBean中的getSingleton会调用addSingletonFactory得到早期bean引用) - 然后填充bean,这里可能涉及到自动装配
- 实际调用了实例化后处理器的after
- 根据mbd的设置,如果它们设置了autowire,就选择autowireByName或byType进行pvs的自动装配(但还没应用到bean实例上)
- byType的autowire需要解冲突,这里使用
AutowireCandidateResolver
和DefaultListableBeanFactory
配合的方式,AutowireCandidateResolver
可以应用@Qualifier
、@Lazy
,DefaultListableBeanFactory
可以根据Primary
和Order
、Priority
等选择候选
- byType的autowire需要解冲突,这里使用
- 调用实例化后处理器的postProcessPropertyValues,允许它对pvs做最终的检查或修改
- 检查未满足的依赖
- 将pvs应用到bean实例上
- 然后initializeBean进入实例化阶段
- 调用aware接口方法
- 调用BeanPostProcessor的before,允许返回代理或包装
- 调用InitMethod
- 调用BeanPostProcessor的after,同样允许返回代理或包装
- 最后进行singleton的依赖冲突检查,如果有实际依赖该singleton的bean,并且执行到此早期singleton已经被包装,所以暴露出的早期引用已经不正确,此时根据配置抛出异常或静默允许这种情况发生
面试题
BeanFactory和FactoryBean的区别
BeanFactory是用于管理bean definition的工厂,可以根据bean definition创建bean并返回给你使用。
FactoryBean是一种特殊的Bean,它并不是最终得到的Bean而是Bean的一个工厂,一些BeanFactory在getBean
时会考虑它(AbstractBeanFactory
),如果createBean
得到的对象类型是FactoryBean
,那么从其中拿出实际的Bean实例。
Spring获取Bean流程
Spring Bean的生命周期
Spring Singleton Bean的三级缓存
参考我的这篇文章:这一次完全搞懂Spring中的循环引用
Spring如何解决循环依赖
参考我的这篇文章:这一次完全搞懂Spring中的循环引用