版本 Spring Framework 6.0.9
1. BeanFactory
BeanFactory接口有五个getBean的重载方法,大致分为名称检索 和 类型检索 (入参同时有名称和类型属于按名称检索,原因是当入参只有类型时,先根据类型从bean工厂获取bean名称,再bean名称作为入参,调用按名称检索的getBean方法)
public interface BeanFactory {
// 根据名称检索bean实例
Object getBean(String name) throws BeansException;
// 根据名称和类型(接口或者超类)检索bean实例
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
// // 根据名称检索bean,指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数参数创建bean实例
Object getBean(String name, Object... args) throws BeansException;
// // 类型(接口或者超类)检索bean实例
<T> T getBean(Class<T> requiredType) throws BeansException;
// 根据类型(接口或者超类)检索bean,指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数参数创建bean实例
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
}
2. getBean
在refresh过程中,spring容器通过bean工厂的getBean方法获取/创建bean实例,一般创建的bean工厂类型都是DefaultListableBeanFactory,按类型检索的getBean由DefaultListableBeanFactory实现,按名称检索的getBean由其父类AbstractBeanFactory实现。
2.1 按类型检索的getBean
DefaultListableBeanFactory类实现了按类型检索的getBean方法,通过对象类型获取ResolvableType后,调用DefaultListableBeanFactory的resolveBean方法解析。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBean(requiredType, (Object[]) null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
// 调用resolveBean方法获取bean对象
Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return (T) resolved;
}
// 省略其他代码
}
resolveBean方法中调用resolveNamedBean方法,解析给定的对象类型,获取唯一匹配的bean实例。resolveNamedBean方法中返回的NamedBeanHolder对象,既包含bean实例,同时保存了bean名称。
@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
// 解析与给定对象类型唯一匹配的 Bean 实例,NamedBeanHolder包含其 Bean 名称。
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
// 尝试从父bean工厂检索
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory dlfb) {
return dlfb.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;
}
调用getBeanNamesForType方法,根据指定类型获取容器中的bean名称。再以bean名称为入参,调用重载的resolveNamedBean方法,方法内调用按名称检索的getBean方法。
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(
ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
// 根据类型获取bean名称
String[] candidateNames = getBeanNamesForType(requiredType);
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
for (String beanName : candidateNames) {
// 不包含给定名称的bean定义 或 该bean定义 autowireCandidate属性为true
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = StringUtils.toStringArray(autowireCandidates);
}
}
if (candidateNames.length == 1) {
return resolveNamedBean(candidateNames[0], requiredType, args);
}
else if (candidateNames.length > 1) {
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
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 集中的主要候选者 Primary
String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
if (candidateName == null) {
// 确定给定 Bean 集中优先级最高的候选项 Priority Ordered
candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
}
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);
}
// 只期望一个匹配的 Bean 但匹配到多个
if (!nonUniqueAsNull) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
}
return null;
}
@Nullable
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<>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
}
所以按类型检索的genBean方法分为两部分:
- 解析给定对象类型获取容器中的bean名称
- 用bean名称调用按名称检索的genBean方法
2.2 按名称检索的getBean
按名称检索的getBean方法,具体实现逻辑在AbstractBeanFactory类里面的doGetBean方法中。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {
return doGetBean(name, requiredType, args, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 省略其他代码
}
// 省略其他代码
}
3. doGetBean
整体执行过程:
- 获取实际的 Bean 名称,如果给定的名称包含工厂Bean前缀&,则去除所有&,如果是别名转换为实际名称
- 从单例池中获取单例对象
- 若存在(获取)
- 根据给定的name,前缀若为&,表明调用者想获取工厂bean,校验当前bean实例是否为bean工厂,是则直接返回,否则抛出BeanIsNotAFactoryException异常
- name不符合工厂bean的规则(前缀为&),说明调用者想要一个普通bean,如果 bean实例不是FactoryBean的子类,直接返回。
- 不符合第1、2点,则说明当前bean实例是FactoryBean的子类,但调用者想获取工厂bean生成的bean实例。先从factoryBeanObjectCache缓存中获取,没有则从工厂bean中获取对象(对象会放到factoryBeanObjectCache缓存)。
- 不存在(创建)
- 如果有父bean工厂, 尝试从中获取
- 如果bean定义设置了dependsOn,先解析dependsOn依赖对象
- 根据bean定义的scope属性,调用createBean创建bean实例(单例、原型、其他)
- 最后将对象进行类型转换
3.1 transformedBeanName
transformedBeanName方法返回 Bean 名称,逻辑分为两部分
- BeanFactoryUtils.transformedBeanName 去掉工厂取消引用前缀&
- canonicalName 将别名解析为规范名称
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// 省略其他代码...
}
循环去掉前缀&,直至name不以&开头为止。
public abstract class BeanFactoryUtils {
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// 如果没有工厂Bean前缀&,直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 循环去除前缀&,直到不以&为前缀
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
// 省略其他代码...
}
canonicalName是AbstractBeanFactory 的父类SimpleAliasRegistry 方法,如果别名缓存map中存在key为name的值,返回name的关联值,即将别名转换成实际的bean名称。
public class SimpleAliasRegistry implements AliasRegistry {
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
// 省略其他代码...
}
3.2 getSingleton
getSingleton方法从三个级别的缓存中获取给定名称的对象,
- 一级缓存:private final Map<String, Object> singletonObjects,初始化完成的bean对象
- 二级缓存:private final Map<String, Object> earlySingletonObjects,实例化但未初始化的bean对象
- 三级缓存:private final Map<String, ObjectFactory<?>> singletonFactories,存储的ObjectFactory是一个lambda表达式,通过getObject方法获取 实例化但未初始化的bean对象
先从一级缓存获取,若不存在判断当前bean名称是否创建中,如果是则从二级缓存中获取。还是获取不到,由于入参allowEarlyReference为true,下一步锁住一级缓存,再尝试从一、二级缓存获取,最后从三级缓存中获取,如果三级缓存有,则调用对象工厂ObjectFactory获取对象,并将对象放入二级缓存,移除三级缓存的引用。
isSingletonCurrentlyInCreation 方法判断singletonsCurrentlyInCreation集合中是否存在给定名称,表示当前bean名称正在创建。添加到singletonsCurrentlyInCreation的位置在创建单例对象过程中,后面标明位置。
3.3 getObjectForBeanInstance
getObjectForBeanInstance方法返回调用者期望的bean实例,逻辑分为三部分,
- 如果name以&开头,说明调用者想要工厂bean,判断当前bean实例是否为FactoryBean,是则直接返回。
- 如果name不以&开头,说明调用者想要普通bean,判断当前bean实例是否为FactoryBean,不是则直接返回。
- 第二点没返回,认为当前bean实例是工厂bean,尝试从工厂bean中获取bean。
3.3.1 isFactoryDereference
isFactoryDereference方法判断name是否以&为前缀开头。
3.3.2 getCachedObjectForFactoryBean
getCachedObjectForFactoryBean方法从factoryBeanObjectCache缓存中获取对象,key为FactoryBean 名称,value为FactoryBean创建的对象。
3.3.3 getMergedLocalBeanDefinition
getMergedLocalBeanDefinition方法返回与父bean定义合并后(如果有)的bean定义,可以理解成完整的bean定义。先从缓存中获取合并的bean定义,如果不为空且不需要重新合并stale=false,直接返回。否则合并bean定义。否则执行合并操作。
getMergedBeanDefinition方法简单理解一下即是 如果当前bean定义设置了父bean名称,则获取父bean定义进行合并,没有则返回的当前bean定义,但两种情况的bean定义类型都转换成了RootBeanDefinition返回。
3.3.4 getObjectFromFactoryBean
getObjectFromFactoryBean方法:调用工厂bean 的getObject方法获取对象。
3.4 isPrototypeCurrentlyInCreation
判断当前bean名称在prototypesCurrentlyInCreation是否存在,如果在说明当前原型bean创建中,抛出BeanCurrentlyInCreationException异常。
、
3.5 originalBeanName
originalBeanName方法包含transformedBeanName方法,都是返回bean名称,区别在于如果name是工厂bean名称,以&为前缀,originalBeanName方法的回参包含&,而transformedBeanName不包含&。
3.6 markBeanAsCreated
typeCheckOnly注释含义说明为了类型检查还是实际使用,在getBean方法中都为false。
markBeanAsCreated方法判断alreadyCreated中是否存在bean名称,如果不存在则锁住mergedBeanDefinitions合并定义缓存,isBeanEligibleForMetadataCaching方法在DefaultListableBeanFactory中判断bean定义是否已经冻结 或 alreadyCreated是否已存在,不是则清空合并bean定义缓存,说明bean定义元数据有可能变化。最后添加到alreadyCreated集合中,表明当前bean名称已创建。
即往alreadyCreated集合中添加beanName
- AbstractBeanFactory#isBeanEligibleForMetadataCaching
- DefaultListableBeanFactory#isBeanEligibleForMetadataCaching
3.7 checkMergedBeanDefinition
checkMergedBeanDefinition判断合并bean定义的abstract属性是否为true,abstract标识当前bean定义允不允许实例化。
3.8 mbd.isSingleton()
如果合并bean定义是单例,即判断其scope属性是否为singleton或空。再调用getSingleton方法获取单例。
getSingleton方法先尝试从缓存中获取,获取不到再调用singletonFactory.getObject()方法,通过单例工厂获取对象,实际返回的是lambda表达式。
3.8.1 singletonFactory.getObject()
入参的ObjectFactory是一个函数式接口,这里的getObject即是getSingleton中的第二个入参try-catch方法,调用createBean(),如果期间报错调用destroySingleton()
3.8.2 beforeSingletonCreation、afterSingletonCreation
inCreationCheckExclusions校验当前bean名称被排除检查,一般都为空,前半部分判断为true,主要看singletonsCurrentlyInCreation集合。
beforeSingletonCreation方法往singletonsCurrentlyInCreation集合中添加bean名称,添加成功表示单例开始创建。
afterSingletonCreation方法从singletonsCurrentlyInCreation集合中移除bean名称,移除成功表示单例创建完成。
3.8.3 addSingleton
singletonFactory.getObject()方法调用成功返回对象后,将newSingleton设置为true,再调用addSingleton方法。
将对象添加到singletonObjects缓存,key为bean名称,value为单例对象。并从二级、三级缓存中移除。再添加到registeredSingletons集合,registeredSingletons存在的bean名称已创建单例对象。
3.9 mbd.isPrototype()
如果合并bean定义的scope属性是prototype,直接调用createBean方法创建对象,没有单例缓存的步骤。
3.9.1 beforePrototypeCreation、afterPrototypeCreation
beforePrototypeCreation、afterPrototypeCreation和上面的3.8.2类似,表明原型bean正在创建。不同在于prototypesCurrentlyInCreation是一个ThreadLocal,并且返回的对象有可能是String,也有可能是set。
3.10 mbd.getScope()
根据合并bean定义的scope属性,从scopes中获取对应的Scope对象,调用其get方法获取对象。scopes是一个map,key为作用域名称,value为作用域对象。
3.10.1 Scope
Scope接口和DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>)一样,第二个入参是lambda表达式,在调用Scope实现类的get方法期间,回调ObjectFactory的getObject方法创建对象。
3.11 adaptBeanInstance
如果bean和requiredType类型不相匹配,则通过类型转换器TypeConverter进行转换,否则直接强转(T) bean。一般情况下,都直接强转。
3.11.1 getTypeConverter
如果没有设置自定义的转换器,getTypeConverter返回一个默认转换器。
默认转换器SimpleTypeConverter的registerCustomEditors方法中,propertyEditorRegistrars集合包含一个ResourceEditorRegistrar实例,该实例在refresh阶段的prepareBeanFactory添加进去。
3.11.2 getTypeConverter().convertIfNecessary(bean, requiredType)
将if条件注释,强制走类型转换器的convertIfNecessary方法,查看调用逻辑。
默认转换器SimpleTypeConverter最终调用的是TypeConverterDelegate#convertIfNecessary方法。逻辑里面尝试使用类型编辑器(如果有)、类型转换服务(如果有)、各个类型判断转换,如果都没有则最终强转,与adaptBeanInstance方法的最后步骤(T) bean强转一样,所以程序走到强转步骤,也能正常解析将object类型强转成User.class返回结果。