基于最新Spring 5.x,详细介绍了finishBeanFactoryInitialization方法的整体流程和部分源码解析,比如DependsOn依赖校验、FactoryBean的特殊获取模式,以及SmartInitializingSingleton、FactoryBean 、SmartFactoryBean扩展点。
上一篇文章:Spring IoC容器初始化源码(5)—prepareBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors方法中,我们主要讲解了ClassPathXmlApplicationContext IoC容器初始化的refresh方法中的prepareBeanFactory配置BeanFactory、postProcessBeanFactory扩展BeanFactory、invokeBeanFactoryPostProcessors回调BeanFactoryPostProcessor扩展点、registerBeanPostProcessors注册BeanPostProcessor扩展点,以及MessageSource和Listener初始化等相关知识点的流程和源码。这一部分内容是连接obtainFreshBeanFactory——注册bean定义的方法和finishBeanFactoryInitialization——实例化bean定义的中间方法。
现在我们继续向下学习refresh
方法的内容,接下来就是finishBeanFactoryInitialization
方法,这个方法是refresh方法内部
的另一个非常重要的方法。该方法用于实例化所有非延迟加载的普通单例bean
。这个方法的源码很多,我们分开解析,本次主要介绍finishBeanFactoryInitialization方法的整体流程以及部分源码解析,比如DependsOn依赖校验、FactoryBean的特殊获取模式,以及SmartInitializingSingleton、FactoryBean 、SmartFactoryBean扩展点。
Spring IoC容器初始化源码 系列文章
Spring IoC容器初始化源码(1)—setConfigLocations设置容器配置信息
Spring IoC容器初始化源码(2)—prepareRefresh准备刷新、obtainFreshBeanFactory加载XML资源、解析<beans/>标签
Spring IoC容器初始化源码(3)—parseDefaultElement、parseCustomElement解析默认、扩展标签,registerBeanDefinition注册Bean定义
Spring IoC容器初始化源码(4)—<context:component-scan/>标签解析、spring.components扩展点、自定义Spring命名空间扩展点
Spring IoC容器初始化源码(5)—prepareBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors方法
Spring IoC容器初始化源码(6)—finishBeanFactoryInitialization实例化Bean的整体流程以及某些扩展点
Spring IoC容器初始化源码(7)—createBean实例化Bean的整体流程以及构造器自动注入
Spring IoC容器初始化源码(8)—populateBean、initializeBean实例化Bean以及其他依赖注入
< context:property-placeholder/>标签以及PropertySourcesPlaceholderConfigurer占位符解析器源码深度解析
三万字的ConfigurationClassPostProcessor配置类后处理器源码深度解析
基于JavaConfig的AnnotationConfigApplicationContext IoC容器初始化源码分析
文章目录
- Spring IoC容器初始化源码 系列文章
- 1 finishBeanFactoryInitialization实例化非延迟单例bean
- 2 preInstantiateSingletons实例化非延迟单例bean
- 3 getMergedLocalBeanDefinition获取合并的BeanDefinition
- 4 isFactoryBean是否是FactoryBean类型
- 5 getBean获取bean实例
- 6 doGetBean获取bean实例
- 7 小结
1 finishBeanFactoryInitialization实例化非延迟单例bean
finishBeanFactoryInitialization是refresh方法中另一个非常重要的方法。该方法用于实例化所有非延迟加载的普通单例bean,此前一些特殊的bean,比如实现了BeanFactoryPostProcessor、BeanPostProcessor、ApplicationEventMulticaster、ApplicationListener等接口的bean定义在前面的方法中已被实例化了。
我们主要看最后一个beanFactory.preInstantiateSingletons()方法,它是核心方法。
/**
* 工厂中的转换服务ConversionService bean 的名称。
* 如果未提供,则应用默认转换规则。
*/
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
/**
* AbstractApplicationContext的方法
* <p>
* 完成此上下文的bean工厂的初始化,初始化所有剩余的非延迟加载的普通单例bean
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
/*
* 1 首先尝试为此上下文初始化ConversionService转换服务的bean定义
*
* 通常,这里的转换服务是配合springMVC使用的,用于将前端传递过来的指定改格式的字符串数据按照自定义转换规则转换成后端接口的类型
* 比如传递String类型的指定时间格式到后台可以转换为Date类型,但是我们一般只需要定义Converter就行了
*
* 这里设置的是AbstractBeanFactory的conversionService属性,如果没有指定conversionService的bean
* 那么普通spring项目默认也不会指定默认值,boot项目会制定默认注册一个ApplicationConversionService服务
*/
//如果beanFactory包含名为"conversionService"的bean定义,并且该bean定义实现了ConversionService接口
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
//那么初始化该bean定义,并且赋给AbstractBeanFactory中的conversionService属性
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
/*
* 2 如果之前没有注册任何嵌入值后处理器(比如PropertySourcesPlaceholderConfigurer bean),
* 那么注册默认嵌入值解析器,主要用于属性值的占位符解析${..:..}。
*/
//如果没有注册任何的嵌入值后处理器,那么注入默认的嵌入值解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
//注意,这里注入的是一个lambda对象,这个对象将会使用环境变量对象的resolvePlaceholders方法来作为resolveStringValue方法的方法体
//它将会使用非严格的PropertyPlaceholderHelper,忽略没有默认值且无法解析的占位符,并且只会使用environment中的属性
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
/*
* 3 如果存在LoadTimeWeaverAware类型的bean定义,那么全部先初始化,一般都没有
* 使用AspectJ在 class 文件加载的时候就进行动态织入
*/
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
//临时的classLoader置为null,停止使用用于类型匹配的临时类加载器
beanFactory.setTempClassLoader(null);
/*
* 4 冻结所有 bean 定义,表示不会进一步修改或处理已注册的 bean 定义。
* configurationFrozen属性设置为true
*/
beanFactory.freezeConfiguration();
/*
* 5 实例化所有剩余的(非延迟加载的)单例bean,这是核心方法
* 如果无法创建其中任何一个单例bean,那么销毁所有已创建的单例bean并且抛出异常。这样做的好处是任何配置错误能够在启动时就被发现
*/
beanFactory.preInstantiateSingletons();
}
2 preInstantiateSingletons实例化非延迟单例bean
preInstantiateSingletons用于实例化所有剩余的非延迟加载的单例bean,包括普通bean、FactoryBean、以及FactoryBean创建的对象(根据情况),并且在此过程中进行一系列的扩展方法的回调!
该方法直接涉及到两个一个扩展点,一个是SmartFactoryBean,另一个是SmartInitializingSingleton,我们会在后面单独讲解。
Spring的源码层级总是很深,preInstantiateSingletons是finishBeanFactoryInitialization的核心方法,而preInstantiateSingletons的核心方法则是getBean方法,用于获取对应beanName的实例对象。
/**
* DefaultListableBeanFactory的属性
* <p>
* 按注册顺序排列的 beanName列表缓存
*/
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/**
* BeanFactory的属性
* <p>
* 用于区分FactoryBean实例本身与FactoryBean创建的实例的beanName的前缀常量
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* DefaultListableBeanFactory的方法
* <p>
* 实例化所有剩余的(非延迟加载的)单例bean,包括FactoryBean
*/
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
//保存beanDefinitionNames的副本用于后续的遍历,以允许init等方法注册新的bean定义
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
/*
* 1 遍历beanDefinitionNames集合,触发所有非延迟加载的的单例bean的实例化和初始化
*/
for (String beanName : beanNames) {
//获取该beanName的已合并的bean定义bd,就是当前bean定义与"parent"属性指定的bean定义合并之后的bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果bd不是抽象的,即abstract不为true,并且bd是单例的,并且bd是非延迟加载的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
/*如果当前beanName对应的bean是FactoryBean*/
if (isFactoryBean(beanName)) {
//通过getBean(&beanName)获取FactoryBean本身的实例
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
//如果输入FactoryBean
if (bean instanceof FactoryBean) {
//强转为FactoryBean类型
FactoryBean<?> factory = (FactoryBean<?>) bean;
//该boolean类型的标志位用于判断这个FactoryBean是否希望立即初始化通过getObject()方法自定义返回的对象
boolean isEagerInit;
//系统安全管理器相关
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
} else {
//是否属于SmartFactoryBean,如果属于,那么获取isEagerInit的返回值
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
//如果为true,那么初始化通过getObject()方法自定义返回的对象
//对于普通的FactoryBean一般都是false
if (isEagerInit) {
getBean(beanName);
}
}
}
/*
* 否则,当前beanName对应的bean是普通bean
* 大部分单例bean都是走这个逻辑都是这个逻辑
*/
else {
//核心方法,调用getBean方法,用于初始化
getBean(beanName);
}
}
}
/*
* 2 遍历beanDefinitionNames集合,触发所有SmartInitializingSingleton类型的bean实例的afterSingletonsInstantiated方法回调
*/
for (String beanName : beanNames) {
//获取单例beanName对应的实例singletonInstance
Object singletonInstance = getSingleton(beanName);
//如果singletonInstance属于SmartInitializingSingleton类型
if (singletonInstance instanceof SmartInitializingSingleton) {
//强制转型
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
//回调afterSingletonsInstantiated方法,即在bean实例化之后回调该方法
//这是一个扩展点,对于所有非延迟初始化的SmartInitializingSingleton类型的单例bean初始化完毕之后会进行回调
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
2.1 SmartInitializingSingleton扩展点
SmartInitializingSingleton是一类特殊的普通单例对象,对于非延迟初始化的SmartInitializingSingleton类型的单例bean,在实例化和初始化完毕之后会回调afterSingletonsInstantiated方法!当然,该方法的回调是在所有剩余的非延迟加载的单例bean实例化以及初始化完毕之后进行回调的,属于非常晚期的回调了。
2.1.1 SmartInitializingSingleton案例
测试类:
/**
* @author lx
*/
public class MySmartBean {
@Component
public static class MySmartBeanA implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("MySmartBeanA SmartInitializingSingleton");
}
@PostConstruct
public void init() {
System.out.println("MySmartBeanA initMethod ");
}
public MySmartBeanA() {
System.out.println("MySmartBeanA constructor");
}
}
@Component
public static class MySmartBeanB implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("MySmartBeanB SmartInitializingSingleton");
}
@PostConstruct
public void init() {
System.out.println("MySmartBeanB initMethod ");
}
public MySmartBeanB() {
System.out.println("MySmartBeanB constructor");
}
}
@Component
public static class MySmartBeanC {
@PostConstruct
public void init() {
System.out.println("MySmartBeanC initMethod ");
}
public MySmartBeanC() {
System.out.println("MySmartBeanC constructor");
}
}
}
spring-config-smart.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.spring.source.smart"/>
</beans>
测试:
@Test
public void smart() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-config-smart.xml");
}
结果如下:
MySmartBeanA constructor
MySmartBeanA initMethod
MySmartBeanB constructor
MySmartBeanB initMethod
MySmartBeanA SmartInitializingSingleton
MySmartBeanB SmartInitializingSingleton
可以看到,afterSingletonsInstantiated方法是在所有单例bean实例化和初始化完毕之后才回调的。
2.2 FactoryBean扩展点
FactoryBean是一种非常重要的Spring扩展机制,很多中间件都利用 FactoryBean 来进行扩展,一般用来用来创建比较复杂的bean。从Spring3.0开始,FactoryBean开始支持泛型。
常见的比如我们需要自定义一个类型转换器,当我只需要实现Converter接口,然后将这个自定义的转换器注册到ConversionServiceFactoryBean这样的一个Spring提供的FactoryBean实例的converters属性中即可。而在使用mybatis-spring依赖时,也可以使用SqlSessionFactoryBean来创建sqlSession。
FactoryBean 是一种特殊的 bean,它是个工厂bean,它本身的创建以及生命周期仍然交给Spring容器管理,但是它可以自定义创建任何其他类型 bean 实例。我们可以通过实现FactoryBean接口,然后自定义需要返回的bean实例逻辑,通过调用getObject() 方法即可返回实例。
从Spring中获取FactoryBean实例以及getObject自定义实例的方式如下,假设我们自定义的FactoryBean的name为"abc":
- getBean(“abc”)方法,实际上返回的就是FactoryBean通过 getObject() 方法返回的自定义的实例。
- getBean("&abc")方法,即加上&前缀,这样才能获取FactoryBean本身的实例。
FactoryBean的getObject() 方法返回的自定义实例同样具有“作用域”这一属性,但是会受到FactoryBean本身的scope属性的影响:
- 如果FactoryBean对象本身是prototype的,那么FactoryBean的返回自定义的实例的作用域也是prototype的,即每次获取自定义的实例都会调用一次getObject方法。与FactoryBean.isSingleton方法的返回值无关。
- 如果FactoryBean对象本身是singleton的,那么FactoryBean的返回自定义的实例的作用域受FactoryBean.isSingleton方法的返回值控制,该方法默认返回true,即默认也是singleton的,仅第一次获取自定义的实例时会调用getObject方法,后续从缓存获取。如果isSingleton返回false,那么作用域就是prototype。
2.2.1 FactoryBean案例
测试类:
/**
* @author lx
*/
public class Custom {
private String property1;
private double property2;
public Custom(String property1, double property2) {
this.property1 = property1;
this.property2 = property2;
}
@Override
public String toString() {
return "Custom{" +
"property1='" + property1 + '\'' +
", property2=" + property2 +
'}';
}
}
自定义的FactoryBean:
/**
* @author lx
*/
@Component
public class MyFactoryBean implements FactoryBean<Custom> {
@Override
public Custom getObject() throws Exception {
return new Custom("自定义返回bean实例", ThreadLocalRandom.current().nextDouble());
}
@Override
public Class<?> getObjectType() {
return Custom.class;
}
}
测试:
@Test
public void factoryBean() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-config-smart.xml");
//不带&前缀,返回的实际上是getObject的返回值
System.out.println(ac.getBean("myFactoryBean"));
System.out.println(ac.getBean("myFactoryBean"));
System.out.println(ac.getBean("myFactoryBean"));
System.out.println(ac.getBean("myFactoryBean"));
//带有&前缀,返回的是自定义的FactoryBean对象本身
System.out.println(ac.getBean("&myFactoryBean"));
System.out.println(ac.getBean("&myFactoryBean"));
System.out.println(ac.getBean("&myFactoryBean"));
System.out.println(ac.getBean("&myFactoryBean"));
}
结果如下:
Custom{property1='自定义返回bean实例', property2=0.6475615106361491}
Custom{property1='自定义返回bean实例', property2=0.6475615106361491}
Custom{property1='自定义返回bean实例', property2=0.6475615106361491}
Custom{property1='自定义返回bean实例', property2=0.6475615106361491}
com.spring.source.factorybean.MyFactoryBean@4abdb505
com.spring.source.factorybean.MyFactoryBean@4abdb505
com.spring.source.factorybean.MyFactoryBean@4abdb505
com.spring.source.factorybean.MyFactoryBean@4abdb505
可以看到,无论是getObect的返回还是对象本身的返回都是单例的,如果我们将MyFactoryBean设置为prototype作用域:
/**
* @author lx
*/
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class MyFactoryBean implements FactoryBean<Custom> {
@Override
public Custom getObject() throws Exception {
return new Custom("自定义返回bean实例", ThreadLocalRandom.current().nextDouble());
}
@Override
public Class<?> getObjectType() {
return Custom.class;
}
}
那么结果都是非单例的:
Custom{property1='自定义返回bean实例', property2=0.649268571619746}
Custom{property1='自定义返回bean实例', property2=0.6127284850093784}
Custom{property1='自定义返回bean实例', property2=0.6605137336971146}
Custom{property1='自定义返回bean实例', property2=0.2033974257287231}
com.spring.source.factorybean.MyFactoryBean@2c039ac6
com.spring.source.factorybean.MyFactoryBean@587d1d39
com.spring.source.factorybean.MyFactoryBean@58c1670b
com.spring.source.factorybean.MyFactoryBean@6b57696f
2.3 SmartFactoryBean扩展点
SmartFactoryBean是一类特殊的FactoryBean,用来对getObject方法的执行时机进行扩展控制,控制对于FactoryBean的getObject方法创建的对象是否需要在容器初始化时同时和FactoryBean实例本身一并急切的初始化。
普通的FactoryBean的getObject方法创建的对象是在第一次获取的时候初始化的,如果我们想要在创建FactoryBean实例之后一并急切的初始化它的getObject方法返回的对象,那么实现SmartFactoryBean接口并重写isEagerInit方法返回true即可(前提是FactoryBean本身是非延迟单例类型)。isEagerInit方法默认返回false,即非急切初始化。
实际上,SmartFactoryBean接口主要用于框架内部。通常,应用提供的FactoryBean接口实现应当只需要实现简单的FactoryBean接口即可,我们作为Spring框架的使用者,SmartFactoryBean接口基本用不到。
2.3.1 SmartFactoryBean案例
测试类:
/**
* @author lx
*/
public class MySmartFactoryBeanIsEagerInit {
/**
* 非延迟单例的SmartFactoryBean,isEagerInit返回false
*/
@Component
public static class MySmartFactoryBeanA implements SmartFactoryBean {
@Override
public Object getObject() throws Exception {
System.out.println("MySmartFactoryBeanA getObject");
return null;
}
@Override
public Class<?> getObjectType() {
return Object.class;
}
@Override
public boolean isEagerInit() {
return false;
}
}
/**
* 非延迟单例的SmartFactoryBean,isEagerInit返回true
*/
@Component
public static class MySmartFactoryBeanB implements SmartFactoryBean {
@Override
public Object getObject() throws Exception {
System.out.println("MySmartFactoryBeanB getObject");
return null;
}
@Override
public Class<?> getObjectType() {
return Object.class;
}
@Override
public boolean isEagerInit() {
return true;
}
}
/**
* prototype的SmartFactoryBean,isEagerInit返回true
*/
@Scope("prototype")
@Component
public static class MySmartFactoryBeanC implements SmartFactoryBean {
@Override
public Object getObject() throws Exception {
System.out.println("MySmartFactoryBeanC getObject");
return null;
}
@Override
public Class<?> getObjectType() {
return Object.class;
}
@Override
public boolean isEagerInit() {
return true;
}
}
/**
* 非延迟单例的普通FactoryBean
*/
@Component
public static class MySmartFactoryBeanE implements FactoryBean {
@Override
public Object getObject() throws Exception {
System.out.println("MySmartFactoryBeanC getObject");
return null;
}
@Override
public Class<?> getObjectType() {
return Object.class;
}
}
}
复用SmartInitializingSingleton扩展点的测试方法,结果如下:
MySmartFactoryBeanB getObject
从结果可知,只有非延迟单例的SmratFactoryBean类型并且isEagerInit方法返回true的bean,在容器实例化的时候才会急切的自动调用getObject方法,初始化从FactoryBean获取的对象。
3 getMergedLocalBeanDefinition获取合并的BeanDefinition
getMergedLocalBeanDefinition方法用于获取已合并的BeanDefinition,返回一个RootBeanDefinition类型的RootBeanDefinition,所谓合并实际上就是XML中的parent属性造成的父类bean和子类bean的定义,我们在IoC的学习部分已经介绍过了,这里子类bean需要合并父类bean的属性,最终返回的BeanDefinition是RootBeanDefinition类型。合并的结果会存入mergedBeanDefinitions缓存map中。
/**
* beanName 到 已合并的 RootBeanDefinition的映射map
*/
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
/**
* AbstractBeanFactory的方法
* <p>
* 返回给定bean的的RootBeanDefinition,如果给定的 bean 具有父类 bean 定义,则遍历、合并所有父类 bean 定义。
*
* @param beanName 要检索合并定义的子类 bean 的名称。
* @return 一个已经合并完毕(如果存在父bean)的RootBeanDefinition类型的bean定义
*/
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
//首先直接尝试根据beanName获取已合并的bean定义mbd
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
//如果mbd不为null,且stale为false不需要重新合并,那么直接返回mbd
//比如在invokeBeanFactoryPostProcessors方法的内部clearMetadataCache方法中就会设置stale状态为true,因为bean定义可能被改变,需要重新合并
if (mbd != null && !mbd.stale) {
return mbd;
}
//否则重新合并bean的定义并且返回,传递beanName以及当前工厂中给定beanName的bean定义
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
/**
* AbstractBeanFactory的方法
* <p>
* 返回给定顶级 bean 的RootBeanDefinition,如果给定 bean是子bean 定义,则它将会与父bean合并然后返回
*
* @param beanName bean定义的名称
* @param bd 当前bean的原始bean定义
* @return 一个已经合并完毕(如果存在父bean)的RootBeanDefinition类型的bean定义
*/
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
//调用另一个getMergedBeanDefinition方法
return getMergedBeanDefinition(beanName, bd, null);
}
/**
* AbstractBeanFactory的方法
* <p>
* 返回给定bean的的RootBeanDefinition,如果给定的 bean 具有父类 bean 定义,则遍历、合并所有父类 bean 定义。
*
* @param beanName bean定义的名称
* @param bd 原始bean定义
* @param containingBd 包含bean,可能为null
* @return 一个已经合并完毕(如果存在父bean)的RootBeanDefinition类型的bean定义
*/
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
//加锁
synchronized (this.mergedBeanDefinitions) {
//用于临时存储bd的MergedBeanDefinition,采用RootBeanDefinition类型,将会返回该变量
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// 如果containingBd为null,尝试获取mbd
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
//如果mbd为null,或者mbd不为null但是stale为false,表示需要重新合并
if (mbd == null || mbd.stale) {
//
previous = mbd;
/*
* 如果parentName属性为null,即对应着XML没有设置parent属性,表示没有设置父类bean
* 那么实际上没有啥可合并的,那么使用当前给定 bean 定义的副本作为RootBeanDefinition,假装合并一下
*/
if (bd.getParentName() == null) {
//如果bd属于RootBeanDefinition类型
if (bd instanceof RootBeanDefinition) {
//使用原始bd克隆一个RootBeanDefinition
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
} else {
//根据bd新建一个RootBeanDefinition
mbd = new RootBeanDefinition(bd);
}
}
/*
* 否则,就是设置了parent属性,那么需要合并父类bean定义
*/
else {
//保存父类bean定义
BeanDefinition pbd;
try {
//返回 父类bean的 名称,必要时删除&引用前缀,并解析别名为规范名称。
String parentBeanName = transformedBeanName(bd.getParentName());
/*
* 如果父类bean的beanName与该bean的beanName不同
*/
if (!beanName.equals(parentBeanName)) {
//那么递归调用getMergedBeanDefinition方法,获取父类bean的MergedBeanDefinition,因为父类bean也可能有父类bean,需要递归调用
//同时,如果在当前 BeanFactory 中找不到bean定义,而又存在父工厂,则会去父工厂中查找。
pbd = getMergedBeanDefinition(parentBeanName);
}
/*
* 如果父类bean的beanName与该bean的beanName相同
*/
else {
//获取父BeanFactory
BeanFactory parent = getParentBeanFactory();
//如果父BeanFactory是ConfigurableBeanFactory类型,则通过父BeanFactory递归的获取父类bean的MergedBeanDefinition
//这表示子工厂可以使用父工厂的 BeanDefinition
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
//否则立即抛出异常,这表示当前bean将parent属性指向了自己
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
//使用父类bean的bean定义pbd构建一个新的RootBeanDefinition对象,深克隆
mbd = new RootBeanDefinition(pbd);
//使用子类bean的bean定义bd覆盖基于父类bean的mbd
mbd.overrideFrom(bd);
}
//如果此前没有设置scope属性,那么设置为默认的singleton
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// 如果内部bean不为null,并且不是singleton单例的,并且外部bean是单例的
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
//那么外部bean设置为内部bean的scope属性
mbd.setScope(containingBd.getScope());
}
// 将beanName与mbd重新放到mergedBeanDefinitions缓存中,以便之后可以直接使用
// 此后仍然有可能重新合并,可能被修改
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
//如果原始的mbd不为null,那么拷贝相当属性到新的mbd中
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
//返回已合并的mbd
return mbd;
}
}
/**
* AbstractBeanFactory的方法
* <p>
* 合并、覆盖bean定义
*
* @param other 子类bean的bean定义
*/
public void overrideFrom(BeanDefinition other) {
//1 覆盖beanClass属性,即XML的class属性
if (StringUtils.hasLength(other.getBeanClassName())) {
setBeanClassName(other.getBeanClassName());
}
//2 覆盖scope属性
if (StringUtils.hasLength(other.getScope())) {
setScope(other.getScope());
}
//3 覆盖scope属性abstract属性
setAbstract(other.isAbstract());
//4 覆盖factoryBeanName属性,即XML的factory-bean属性
if (StringUtils.hasLength(other.getFactoryBeanName())) {
setFactoryBeanName(other.getFactoryBeanName());
}
//5 覆盖factoryMethodName属性,即XML的factory-method属性
if (StringUtils.hasLength(other.getFactoryMethodName())) {
setFactoryMethodName(other.getFactoryMethodName());
}
//覆盖role属性,source属性、attributes属性
setRole(other.getRole());
setSource(other.getSource());
copyAttributesFrom(other);
if (other instanceof AbstractBeanDefinition) {
AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
//7 覆盖beanClass属性,就是通过全路径的className获取Class对象
if (otherAbd.hasBeanClass()) {
setBeanClass(otherAbd.getBeanClass());
}
//覆盖全部的自己设置了值的同名<constructor-arg>标签属性
if (otherAbd.hasConstructorArgumentValues()) {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
}
//覆盖全部的自己设置了值的同名<property>标签属性
if (otherAbd.hasPropertyValues()) {
getPropertyValues().addPropertyValues(other.getPropertyValues());
}
//覆盖全部的自己设置了值的同名<lookup-method>、<replaced-method>标签属性
if (otherAbd.hasMethodOverrides()) {
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
}
//覆盖lazyInit属性,即XML的lazy-init属性
Boolean lazyInit = otherAbd.getLazyInit();
if (lazyInit != null) {
setLazyInit(lazyInit);
}
//覆盖autowire属性,即XML的autowire属性
setAutowireMode(otherAbd.getAutowireMode());
setDependencyCheck(otherAbd.getDependencyCheck());
//覆盖dependsOn属性,即XML的depends-on属性
setDependsOn(otherAbd.getDependsOn());
//覆盖autowireCandidate属性,即XML的autowire-candidate属性
setAutowireCandidate(otherAbd.isAutowireCandidate());
//覆盖primary属性,即XML的primary属性
setPrimary(otherAbd.isPrimary());
//覆盖qualifier属性
copyQualifiersFrom(otherAbd);
setInstanceSupplier(otherAbd.getInstanceSupplier());
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
if (otherAbd.getInitMethodName() != null) {
setInitMethodName(otherAbd.getInitMethodName());
setEnforceInitMethod(otherAbd.isEnforceInitMethod());
}
if (otherAbd.getDestroyMethodName() != null) {
setDestroyMethodName(otherAbd.getDestroyMethodName());
setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
}
setSynthetic(otherAbd.isSynthetic());
setResource(otherAbd.getResource());
} else {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
getPropertyValues().addPropertyValues(other.getPropertyValues());
setLazyInit(other.isLazyInit());
setResourceDescription(other.getResourceDescription());
}
}
3.1 transformedBeanName转换beanName
transformedBeanName用于转换、返回bean的名称,必要时删除全部&引用前缀,并解析别名为规范名称。
/**
* AbstractBeanFactory的方法
* <p>
* 返回 bean 名称,必要时删除&引用前缀,并解析别名为规范名称。
*
* @param name 用户指定的名称
* @return 转换后的名称
*/
protected String transformedBeanName(String name) {
//首先调用transformedBeanName的方法去除全部"&" 前缀
//随后调用canonicalName方法将别名解析为规范名称
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
/**
* BeanFactory的属性
* <p>
* 一个beanName的前缀,用于将FactoryBean实例本身和FactoryBean创建的实例区分开
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* BeanFactoryUtils的方法
* <p>
* 返回实际的 bean 名称,去掉所有的"&" 前缀
*
* @param name bean name
* @return 转换的名称
*/
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
//如果不是以"&" 前缀开头,返回原值
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 如果beanName带有 "&" 前缀,则去掉所有的"&" 前缀
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
//循环去掉所有的"&" 前缀
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
/**
* SimpleAliasRegistry的方法
* <p>
* 循环的确定原始名称,将别名解析为规范名称。
*
* @param name 用户指定的名称
* @return 转换的名称
*/
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
//很简单,就是循环的从别名映射缓存中获取值,如果某次获取的值为null,那么这个"别名"就是真的名称
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
3.2 getMergedBeanDefinition支持父BeanFactory查找
由于Spring支持子工厂和父工厂,那么在对于父类bean进行合并的时候,如果在当前 BeanFactory 中找不到给定名称的父类bean定义,将会考虑从父工厂中查找并且合并给定名称的父类bean定义。
非web应用通常没有父BeanFactory,但是在web应用中的,Spring 的 BeanFactory 是 “父工厂”,Spring MVC 的 BeanFactory 就是 “子工厂”,因此要需要注意。
/**
* 返回给定 bean 名称的"合并"Bean 定义,必要时将子 bean 定义与父级合并。
* 如果在当前 BeanFactory 中找不到给定名称的bean定义,将会考虑从父工厂中查找bean定义
*
* @param name 用于检索的合并bean定义的 bean 的名称(可能是别名)
* @return 一个已经合并完毕(如果存在父bean)的RootBeanDefinition类型的bean定义
* @throws NoSuchBeanDefinitionException 如果没有给定名称的 bean
* @throws BeanDefinitionStoreException 无效的 bean 定义
*/
@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
//返回 bean 名称,必要时删除&引用前缀,并解析别名为规范名称。
String beanName = transformedBeanName(name);
// 如果在当前 BeanFactory 中找不到给定名称的bean定义,将会考虑从父工厂中查找bean定义
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
//从父工厂中查找并且合并bean定义
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
}
// 否则,在本地工厂解析合并的 bean 定义。
return getMergedLocalBeanDefinition(beanName);
}
4 isFactoryBean是否是FactoryBean类型
用于判断bean是否是FactoryBean类型。
/**
* AbstractBeanFactory的方法
* <p>
* 确定给定名称的 bean 是否是FactoryBean
*
* @param name 要检查的bean name
* @return bean 是否是 FactoryBean
*/
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
//确定真实的beanName(必要时删除&引用前缀,并解析别名为规范名称。)
String beanName = transformedBeanName(name);
//尝试获取bean实例缓存,不允许创建早期引用
Object beanInstance = getSingleton(beanName, false);
//如果不为null,那么判断是否属于FactoryBean类型并返回
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
}
//到这里,说明还没有被初始化,那么检查bean定义
//如果工厂中没有该beanName的bean定义,并且父工厂属于ConfigurableBeanFactory,非web环境下一般父工厂都为null
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
//委托到父工厂中查找
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
//到这里还没有返回
//通过该beanName的MergedBeanDefinition来检查对应的Bean是否为FactoryBean
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
/**
1. 通过该beanName的MergedBeanDefinition来检查对应的Bean是否为FactoryBean
2. 3. @param beanName bean name
4. @param mbd 相应的 bean 定义
*/
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
//获取isFactoryBean属性
Boolean result = mbd.isFactoryBean;
//如果该属性还没有赋值
if (result == null) {
//那么预测指定 bean 的最终 bean 类型是否是FactoryBean类型
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
//为该属性赋值
mbd.isFactoryBean = result;
}
//返回结果
return result;
}
4.1 getSingleton尝试获取单例bean缓存实例
单例对象如果没有创建过一般的都是返回null,如果此前创建过那就返回创建的实例。这部分代码还用于解决循环依赖,这个问题后面创建bean的时候再说,并且该方法在后面会经常见到,到时候不再赘述!
- 首先尝试从singletonObjects单例bean实例的缓存中获取给定beanName的实例singletonObject;
- 如果singletonObject为null,并且正在创建该beanName对应的单例bean,即singletonsCurrentlyInCreation缓存中包含该beanName,后面我们会知道,在调用createBean方法前后,就会将beanName加入、移除该缓存:
- 从早期的单例对象缓存earlySingletonObjects中获取单例对象赋值给singletonObject,这里的对象可能仅仅是被初始化了,还未进行属性填充。
- 如果singletonObject还是为null,并且允许创建早期引用,即第二个参数是true:
- 从单例工厂缓存singletonFactories中尝试指定获取beanName的单例工厂singletonFactory,通过单例工厂创建一个单例对象。
- 将该对象存入早期单例对象缓存earlySingletonObjects中,并将该beanName对应的单例工厂从singletonFactories中移除,这个单例工厂已经没用了。实际上一个beanName的实例只能在“三级缓存”中的某一个缓存中,因此所谓的“三级缓存”是不准确的!
//--------DefaultSingletonBeanRegistry的相关属性---------
//Spring bean创建的"三级缓存":singletonObjects、earlySingletonObjects、singletonFactories
//用于解决循环引用
/**
* beanName 到 bean instance 的单例bean实例map缓存
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* beanName 到 bean instance的早期单例bean实例map缓存
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/**
* beanName 到 ObjectFactory的单例bean工厂实例map缓存
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* 当前正在创建中的 bean 的名称
*/
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/**
* DefaultSingletonBeanRegistry的方法
* <p>
* 返回在给定名称下注册的(原始)单位对象。
* 检查已实例化的单例bean,并允许创建用来解决循环引用的早期引用。
*
* @param beanName 要查找的bean name
* @param allowEarlyReference 是否应创建早期引用
* @return 已注册的单位对象,如未找到,则为 null
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//单例bean实例的缓存
Object singletonObject = this.singletonObjects.get(beanName);
//如果没有创建bean实例,并且正在创建该beanName对应的单例bean
//即判断对应的singletonsCurrentlyInCreation缓存是否包含该beanName
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//加锁
synchronized (this.singletonObjects) {
//从早期的单例对象缓存中获取单例对象赋值给singletonObject,这些对象还未进行属性填充
singletonObject = this.earlySingletonObjects.get(beanName);
//如果singletonObject还是为null,并且允许创建早期引用
if (singletonObject == null && allowEarlyReference) {
//从单例工厂缓存中尝试指定获取beanName的单例工厂singletonFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果singletonFactory不为null
if (singletonFactory != null) {
//通过单例工厂创建一个单例对象
singletonObject = singletonFactory.getObject();
//存入早期单例对象缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//将该beanName对应的单例工厂移除,这个单例工厂已经没用了
//一个beanName的实例只能在"三级缓存"中的某一个缓存中
this.singletonFactories.remove(beanName);
}
}
}
}
//返回单例对象
return singletonObject;
}
/**
* 返回指定的单例当前是否在创建中(在整个工厂内)。
*
* @param beanName bean name
*/
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
5 getBean获取bean实例
getBean(beanName)是Spring容器初始化过程中的又一个核心方法,该方法用于实例化并返回给定beanName的实例。
我们外部调用上下文容器的getBean方法实际上内部就是调用它的BeanFactory的getBean(beanName)方法。
/**
* AbstractBeanFactory的方法
* <p>
* 根据bean name 返回指定 bean 的实例
*
* @param name bean name
* @return bean实例
*/
@Override
public Object getBean(String name) throws BeansException {
//调用doGetBean方法
//bean预期的类型requiredType和使用的显式参数args都传递null
return doGetBean(name, null, null, false);
}
6 doGetBean获取bean实例
getBean的方法内部实际上是调用doGetBean方法,在Spring中,一般真正执行相关逻辑的方法都会以do开头。这个方法是我们重点关注的方法,我们将会使用大量的篇幅来解析Spring具体是如何创建对象的。
doGetBean方法会首先从缓存获取实例,如果获取到了就直接返回,获取不到就会走创建bean实例的逻辑。
- 调用transformedBeanName返回 bean 名称,必要时删除&引用前缀,并解析别名为规范名称。
- 随后调用 getSingleton(beanName) 方法尝试直接从缓存中获取实例sharedInstance,允许早期实例创建。如果从一级缓存singletonObjects中获取不到,会判断是否当前实例是否正在创建中,如果在创建中,说明出现了循环引用,此时从二级缓存earlySingletonObjects获取,还是获取不到,那么尝试从三级缓存singletonFactories中获取早期的bean实例放入二级缓存earlySingletonObjects,随后删除对应的三级缓存(Spring中一个bean实例只能出现在某一级别的缓存中,和普通的“缓存”不一样)。
- 如果缓存获取的实例sharedInstance不为null,那么说明此前创建过该bean实例,或者已经创建了早期实例。
- 随后调用getObjectForBeanInstance从sharedInstance获取要返回的bean对象并返回,方法结束。如果是普通bean实例,那么直接返回sharedInstance,如果是 FactoryBean 实例,则获取对应 FactoryBean实例本身或其创建的对象。这个方法在后面也会被调用到。
- 如果缓存获取的实例sharedInstance为null,那么需要创建该bean实例:
- 如果指定beanName是原型bean,并且当前正在创建中(在当前线程内),而现在又在被创建,说明出现了循环引用,那么抛出异常。Spring可以帮我们解决setter方法和注解反射的循环依赖注入,但是互相依赖的两个bean不能都是prototype原型的。
- 如果存在父BeanFactory,并且当前工厂的beanDefinitionMap缓存不包含该beanName的bean定义,那么尝试从父BeanFactory中通过调用getBean方法获取bean实例并返回。
- 如果调用该doGetBean方法不是为了类型检查,那么将当前的beanName存放到AlreadeyCreated的缓存set集合,用于标识这个bean被创建了或者即将被创建。
- 保证当前bean所依赖的bean的先被初始化。请注意,这里的依赖是depends-on属性或者@DependsOn注解指定的beanName,而不是依赖的属性。depends-on属性或者@DependsOn注解指定的beanName同样可能出现循环依赖,这是不被允许的。
- 这里开始创建bean实例:
- 如果bean定义是singleton单例的,调用getSingleton(beanName, singletonFactory)和createBean方法创建单例对象sharedInstance,随后调用getObjectForBeanInstance方法处理,最终获取到bean对象。 这里的singletonFactory参数是一个lambda表达式对象,它的getObject方法实际上就是调用的createBean方法来创建bean实例。
- 如果bean定义是prototype原型的,调用createBean方法创建对象sharedInstance,随后调用getObjectForBeanInstance方法处理,最终获取到bean对象。在createBean方法之前和之后还有两个回调方法beforePrototypeCreation和afterPrototypeCreation。
- 如果bean定义是其它类型的,那么使用各自的scope实现来创建scopedInstance实例,随后调用getObjectForBeanInstance方法处理,最终获取到bean对象。在createBean方法之前和之后还有两个回调方法beforePrototypeCreation和afterPrototypeCreation。
- bean创建失败之后,将beanName从alreadyCreated缓存中移除。
- 检查所需的目标类型是否与bean 实例的类型相匹配或者兼容,如果兼容就直接返回bean。这里的兼容的要求是bean实例属于requiredType的类型以及子类,如果不匹配或者兼容,那么使用转换服务进行类型转换再返回,转换失败抛出异常!
/**
* AbstractBeanFactory的方法
* <p>
* 返回指定 bean 的实例,该实例可能是共享的或独立的。
*
* @param name 要检索的 bean 的名称
* @param requiredType 要检索的 bean 所预期的类型
* @param args 使用显式参数创建 bean 实例时使用的参数(仅在创建新实例时应用, 而不是检索现有实例),一般没有
* @param typeCheckOnly 实例是否是为了类型检查而获取的,而不是为实际使用而获取的
* @return bean 实例
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
/*
* 1 返回 bean 名称,必要时删除&引用前缀,并解析别名为规范名称。
*/
String beanName = transformedBeanName(name);
Object bean;
/*
* 2 首先调用getSingleton尝试直接从单例缓存中获取已经实例,前面讲过了该方法,可以用来解决循环依赖
* 这里的一个参数的getSingleton方法,内部同样会调用两个参数getSingleton方法,并且第二个参数为true,表示允许创建早期引用
*/
Object sharedInstance = getSingleton(beanName);
/*
* 3 如果从缓存中获取到了bean实例,并且args为null
*/
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
//如果是正在创建该beanName对应的单例bean,那么说明是尚未完全初始化的单例
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//返回sharedInstance对应的实例对象
//如果是普通bean实例,那么直接返回sharedInstance,如果是 FactoryBean 实例,则获取FactoryBean实例本身或其创建的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
/*4 如果从缓存中没有获取到了sharedInstance实例,那么就需要创建对应的实例了*/
else {
/*
* 4.1 如果指定beanName是原型bean,并且当前正在创建中(在当前线程内),而现在又在被创建,说明出现了循环引用,那么抛出异常
* Spring可以帮我们解决setter方法和反射方法的循环依赖注入,但是互相依赖的两个bean不能都是prototype的
*/
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//获取父BeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
/*
* 4.2 如果存在父BeanFactory,并且当前工厂的beanDefinitionMap缓存不包含该beanName的bean定义
* 那么尝试从父BeanFactory中获取bean实例并返回
*/
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//确定原始 bean 名称,将给定的的别名解析为规范名称。
//内部调用了transformedBeanName方法,区别就是如果原来name存在&前缀,那么返回的规范名称同样会加上&前缀
String nameToLookup = originalBeanName(name);
/*如果parentBeanFactory属于AbstractBeanFactory类型,一般都属于*/
if (parentBeanFactory instanceof AbstractBeanFactory) {
//尝试在parentBeanFactory中获取bean对象实例
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
/*否则,使用显式 arg 委派给父BeanFactory*/
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
/*否则,如果requiredType不为null,那么委托给标准 getBean 方法。*/
else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
/*否则,调用parent的同名方法*/
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
/*
* 4.3 如果不是为了类型检查
* 那么将当前的beanName存放到alreadyCreated的缓存set集合,用于标识这个bean被创建了或者即将被创建
*/
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
/*4.4 因为上面的markBeanAsCreated可能已经清除了该缓存,这里重新获取合并之后的bean定义mbd*/
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查合并之后的mbd,如果具有抽象属性,那么抛出异常
checkMergedBeanDefinition(mbd, beanName, args);
/*
* 4.5 保证当前bean所依赖的bean的先被初始化
* 请注意,这里的依赖是depends-on属性或者@DependsOn注解指定的beanName,而不是依赖的属性
* depends-on属性或者@DependsOn注解指定的beanName同样可能出现循环依赖,这是不被允许的
*/
//获取当前bean定义依赖的beanName数组
String[] dependsOn = mbd.getDependsOn();
//如果dependsOn不为null
if (dependsOn != null) {
//遍历dependsOn数组
for (String dep : dependsOn) {
//检查dep是否又依赖于beanName,即检查是否存在循环依赖。比如A depends-on B,B depends-on A
if (isDependent(beanName, dep)) {
//Spring不允许这种循环依赖存在,直接抛出异常,但是这里不一定能立即检查出来,因为dependentBeanMap此前可能没有加入依赖关系
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//没有抛出异常,那么将dep和beanName的依赖关系注册到dependentBeanMap和dependenciesForBeanMap缓存中
registerDependentBean(dep, beanName);
try {
//递归调用getBean方法,先创建DependsOn依赖的bean实例
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
/*
* 4.6 创建当前bean实例
*/
/*如果mbd是单例的*/
if (mbd.isSingleton()) {
//调用getSingleton方法获取实例,这里是真正的完整bean实例创建的方法
//第二个参数使用了Java8的lambda表达式语法,ObjectFactory的getObject方法调用的是createBean方法
sharedInstance = getSingleton(beanName, () -> {
try {
//getObject方法实际上就是调用的createBean方法来创建bean实例
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
//抛出异常之后,从单例缓存中删除对应的实例
destroySingleton(beanName);
throw ex;
}
});
//返回sharedInstance对应的实例对象
//如果是普通bean实例,那么直接返回sharedInstance,如果是 FactoryBean 实例,则获取FactoryBean实例本身或其创建的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
/*如果mbd是原型的,每次都需要创建新对象*/
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
//在原型bean实例创建之前进行回调
//默认实现是将当前原型beanName注册到当前正在创建的bean缓存prototypesCurrentlyInCreation中
beforePrototypeCreation(beanName);
//创建bean实例
prototypeInstance = createBean(beanName, mbd, args);
} finally {
//在原型bean实例创建之后进行回调
//默认实现将原型标记为不在创建中,即从当前正在创建的bean缓存prototypesCurrentlyInCreation中移除
afterPrototypeCreation(beanName);
}
//返回sharedInstance对应的实例对象
//如果是普通bean实例,那么直接返回sharedInstance,如果是 FactoryBean 实例,则获取FactoryBean实例本身或其创建的对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
/*其它类型的scope*/
else {
//获取scope属性值
String scopeName = mbd.getScope();
//scopeName不能为null以及""
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
//从scopes缓存中根据scopeName获取scope
Scope scope = this.scopes.get(scopeName);
//没找到scope,那么抛出异常
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
//使用各自的scope实现来创建scopedInstance实例
Object scopedInstance = scope.get(beanName, () -> {
//在原型bean实例创建之前进行回调
//默认实现是将当前原型beanName注册到当前正在创建的bean缓存prototypesCurrentlyInCreation中
beforePrototypeCreation(beanName);
try {
//创建bean实例
return createBean(beanName, mbd, args);
} finally {
//在原型bean实例创建之后进行回调
//默认实现将原型标记为不在创建中,即从当前正在创建的bean缓存prototypesCurrentlyInCreation中移除
afterPrototypeCreation(beanName);
}
});
//返回sharedInstance对应的实例对象
//如果是普通bean实例,那么直接返回sharedInstance,如果是 FactoryBean 实例,则获取FactoryBean实例本身或其创建的对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
} catch (BeansException ex) {
//bean创建失败之后,将beanName从alreadyCreated缓存中移除
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
//检查所需的目标类型是否与bean 实例的类型相匹配或者兼容,这里的兼容的要求是bean实例属于requiredType的类型以及子类
//如果不匹配或者兼容,那么使用转换服务进行类型转换,如果兼容就直接返回bean
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
//转换类型
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
//返回
return 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;
}
6.1 getObjectForBeanInstance根据beanName获取要返回的对象
该方法主要用于对FactoryBean的特殊处理!
- 如果是普通Bean则会直接返回传入的sharedInstance本身。
- 如果是FactoryBean则根据传递的参数beanName判断可能返回FactoryBean实例本身或者FactoryBean.getObject方法返回的实例。
/**
* 当前线程正在创建的 bean 的名称
* 支持obtainFromSupplier方法加入的属性
*/
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
/**
* AbstractAutowireCapableBeanFactory的方法
* <p>
* 为了支持Java8的obtainFromSupplier方法
*/
@Override
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//获取当前线程正在创建的bean的名称,主要是支持obtainFromSupplier方法,一般情况获取到的值都为null
String currentlyCreatedBean = this.currentlyCreatedBean.get();
//如果不为null
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
//如果为null,一般走这一步逻辑,调用父类AbstractBeanFactory的同名方法
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
/**
* AbstractAutowireCapableBeanFactory的父类AbstractBeanFactory的方法
* <p>
* 获取给定 bean 实例,在工厂Bean的情况下获取 bean 实例本身或其创建的对象。
*
* @param beanInstance 共享的bean实例
* @param name 可能包含工厂&前缀的bean name,传递的数据
* @param beanName 规范的beanName
* @param mbd 已合并的bean定义,如果beanInstance此前就被创建了,那么mbd为null
* 如果beanInstance是参差被创建的,那么那么mbd不为null
* @return 公开的 bean 对象
*/
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//如果给定的name是以“&”为前缀,这表示想要获取FactoryBean对象本身
if (BeanFactoryUtils.isFactoryDereference(name)) {
//如果beanInstance属于NullBean,这是对getObject方法返回的null的包装
if (beanInstance instanceof NullBean) {
//那么返回beanInstance
return beanInstance;
}
//如果类型不是FactoryBean,直接抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
//如果mbd不为null,那么isFactoryBean属性置为true
if (mbd != null) {
mbd.isFactoryBean = true;
}
//如果类型是FactoryBean,直接返回beanInstance
return beanInstance;
}
//到这里表示name不带有&前缀,即我们想要获取普通bean或者FactoryBean内部的自定义bean
//如果beanInstance不是FactoryBean实例,那么就是普通bean实例,那么直接返回beanInstance就行
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
//到这里,表示beanInstance属于FactoryBean实例,但是我们想要获取FactoryBean内部的自定义bean
Object object = null;
//如果mbd不为null
if (mbd != null) {
//isFactoryBean属性设置为true
mbd.isFactoryBean = true;
}
//否则,如果mbd为null
else {
//尝试从factoryBeanObjectCache缓存中直接获取该FactoryBean的getObject方法创建的对象实例
//如果是单例的,并且此前获取过,那么就会存入缓存中,如果是第一次获取,那么就获取不到
object = getCachedObjectForFactoryBean(beanName);
}
//如果object为null,说明没有缓存
if (object == null) {
//beanInstance强转为FactoryBean类型的实例factory
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//如果mbd为null,并且beanDefinitionMap中包含beanName的缓存 Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
//通过getMergedLocalBeanDefinition方法获取该beanName合并之后的bean定义,此前讲过该方法
mbd = getMergedLocalBeanDefinition(beanName);
}
//返回此 bean 定义是否不为null,并且是否是"合成"的,即不是由应用程序本身定义的,一般都是自己建立的,默认false
boolean synthetic = (mbd != null && mbd.isSynthetic());
//从FactoryBean实例获取getObject方法创建的对象实例的逻辑交给getObjectFromFactoryBean方法完成
//!synthetic用来表示是否需要执行beanPostProcess后处理方法,一般都需要
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
6.1.1 getCachedObjectForFactoryBean从缓存获取对象实例
该方法从factoryBeanObjectCache中获取给定beanName的getObject方法返回的对象实例,可能返回null,即还没有存入缓存。
/**
* FactoryBeanRegistrySupport的属性
* <p>
* FactoryBean name 到 getObject方法创建的单例对象实例 的缓存
*/
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
/**
* FactoryBeanRegistrySupport的方法
* <p>
* 从factoryBeanObjectCache 获取公开的对象(如果存在缓存)。
*
* @param beanName FactoryBean name
* @return 从factoryBeanObjectCache获得的对象,如果没有被缓存,那么返回null
*/
@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
6.1.2 getObjectFromFactoryBean从FactoryBean获取对象实例
如果factoryBeanObjectCache缓存中没有对应的beanName的缓存,那么调用getObjectFromFactoryBean方法,用于从FactoryBean实例中获取getObject方法返回的对象实例。
如果在本次getObjectFromFactoryBean方法的调用过程中调用了getObject方法,并且需要进行后处理,那么还会执行所有BeanPostProcessor 的 postProcessAfterInitialization 后处理方法。
从该方法源码中我们也能看到,getObject方法同样受到它所在的FactoryBean的scope属性的影响,如果FactoryBean本身是单例的并且isSingleton方法true,那么getObject返回的也是单例的,对应的返回值将会缓存到factoryBeanObjectCache缓存中,否则,每次都会重新调用getObject方法取得返回值。
factoryBeanObjectCache缓存位于FactoryBeanRegistrySupport类中,专门用于存放FactoryBean的beanName 到 getObject方法返回的实例的缓存,前提是FactoryBean本身是单例的并且isSingleton方法true。
/**
* AbstractBeanFactory的方法
* <p>
* 从给定的FactoryBean获取getObject方法要公开的对象实例。
*
* @param factory FactoryBean 实例
* @param beanName beanName
* @param shouldPostProcess bean是否要进行后处理,一般都需要
* @return 从FactoryBean获取的对象
*/
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
/*如果FactoryBean是单例的并且singletonObjects缓存中以包含给定beanName的实例*/
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
//尝试从FactoryBean创建的单例对象的factoryBeanObjectCache缓存中获取对应beanName的实例
Object object = this.factoryBeanObjectCache.get(beanName);
//如果object为null,说明此前没有获取过
if (object == null) {
//调用doGetObjectFromFactoryBean方法,获取getObject方法返回的对象
object = doGetObjectFromFactoryBean(factory, beanName);
// 再次从factoryBeanObjectCache缓存中获取对应beanName的实例
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
/*如果alreadyThere不为null,说明其他线程已经创建并加入缓存了*/
if (alreadyThere != null) {
object = alreadyThere;
}
/*否则,说明alreadyThere为null,那么本次的getObjectFromFactoryBean方法是第一次获取实例*/
else {
//是否需要回调处理
if (shouldPostProcess) {
//如果当前FactoryBean还在创建过程中
if (isSingletonCurrentlyInCreation(beanName)) {
//那么直接返回object,不进行回调,也不进行缓存
return object;
}
//回调之前的检查
beforeSingletonCreation(beanName);
try {
//执行所有已注册的BeanPostProcessor的postProcessAfterInitialization方法
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
} finally {
//回调之后的检查
afterSingletonCreation(beanName);
}
}
//如果singletonObjects缓存中以包含给定beanName的实例
if (containsSingleton(beanName)) {
//那么同样将object也存入factoryBeanObjectCache缓存,下一次再来获取时直接从缓存中获取
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
//返回object
return object;
}
}
/*否则,表示不是单例的*/
else {
//每一次请求,都调用FactoryBean的getObject方法获取对象实例
Object object = doGetObjectFromFactoryBean(factory, beanName);
//如果需要进行回调
if (shouldPostProcess) {
try {
//执行所有已注册的BeanPostProcessor的postProcessAfterInitialization方法
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
//返回object
return object;
}
}
6.1.2.1 doGetObjectFromFactoryBean调用getObject方法对象实例
doGetObjectFromFactoryBean方法位于FactoryBeanRegistrySupport中,该方法才是真正的调用FactoryBean的getObject方法,返回getObject方法获取到的对象。
/**
* FactoryBeanRegistrySupport的方法
* <p>
* 从给定的FactoryBean调用getObject方法获取要公开的对象。
*
* @param factory FactoryBean instance
* @param beanName beanName
* @return 从FactoryBean获得的对象
*/
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
//安全管理器相关,一般都为null,因此会走下面else的逻辑
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
//直接调用FactoryBean的getObject方法获取bean对象实例
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
//如果object为null
if (object == null) {
//如果该factoryBean还在创建过程中,那么抛出异常,不接受尚未完全初始化的 FactoryBean 返回的 null 值
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
//否则使用一个NullBean实例来表示getObject方法就是返回的null,避免空指针
object = new NullBean();
}
//返回object
return object;
}
6.1.2.2 postProcessObjectFromFactoryBean执行后处理
如果调用了getObject方法,并且需要进行后处理(一般都需要),那么对该方法返回的对象(无论是不是单例的)执行所有已注册的BeanPostProcessor的postProcessAfterInitialization扩展方法。Spring IoC本身对于postProcessAfterInitialization回调方法并没有什么特殊逻辑。
可以看到,在执行后处理的过程中如果某个BeanPostProcessor的postProcessAfterInitialization方法的返回null,那么后续的BeanPostProcessor的postProcessAfterInitialiation方法就不会被执行了。
/**
* AbstractAutowireCapableBeanFactory的方法
* <p>
* 应用所有已注册 BeanPost 处理器的postProcessAfterInitialization回调,让它们有机会对从 FactoryBean 获得的对象进行后处理(例如,自动代理它们)。
*
* @param object 需要进行后处理的bean实例
* @param beanName beanName
* @return 最后一个BeanPostProcessor的postProcessAfterInitialization方法的返回结果
*/
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
//调用applyBeanPostProcessorsAfterInitialization方法
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
/**
* AbstractAutowireCapableBeanFactory的方法
*
* @param existingBean 需要进行后处理的bean实例
* @param beanName beanName
* @return 最后一个BeanPostProcessor的postProcessAfterInitialization方法的返回结果
*/
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍历所有已注册的BeanPostProcessor,按照遍历顺序回调postProcessAfterInitialization方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
//如果途中某个processor的postProcessAfterInitialization方法返回null,那么不进行后续的回调
//直接返回倒数第二个processor的postProcessAfterInitialization方法的返回值
if (current == null) {
return result;
}
//改变result指向当前的返回值
result = current;
}
//返回result
return result;
}
6.2 originalBeanName获取规范beanName
originalBeanName方法用于确定原始 bean 名称,将给定的的别名解析为规范名称。内部调用了transformedBeanName方法,区别就是如果原来name存在&前缀,那么返回的规范名称同样会加上&前缀。
/**
* AbstractBeanFactory的方法
* <p>
* 确定原始 bean 名称,将本地定义的别名解析为规范名称。
*
* @param name the user-specified name
* @return the original bean name
*/
protected String originalBeanName(String name) {
//调用transformedBeanName方法,必要时删除全部&引用前缀,并解析别名为规范名称。
String beanName = transformedBeanName(name);
//name是以&为前缀
if (name.startsWith(FACTORY_BEAN_PREFIX)) {
//那么解析之后的规范名称同样加上&前缀
beanName = FACTORY_BEAN_PREFIX + beanName;
}
//返回beanName
return beanName;
}
6.3 markBeanAsCreated标记创建
如果不是为了类型检查,将调用markBeanAsCreated方法将指定的 beanName存放到alreadyCreated的缓存set集合,即标记为已创建或即将创建。这允许 bean 工厂优化其缓存,以重复创建指定的 bean。
还会清除mergedBeanDefinitions缓存中该beanName的合并缓存,后面需要重新获取。
/**
* AbstractBeanFactory的属性
* <p>
* 已创建至少一次的 beanName 缓存
*/
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
/**
* AbstractBeanFactory的方法
* <p>
* 将指定的 bean 标记为已创建(或即将创建)。
* 这允许 bean 工厂优化其缓存,以重复创建指定的 bean。
*
* @param beanName bean 的名字
*/
protected void markBeanAsCreated(String beanName) {
//如果alreadyCreated缓存没有包含当前beanName
if (!this.alreadyCreated.contains(beanName)) {
//加锁
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
//在创建bean期间有可能有一些元数据的变化,因此清除mergedBeanDefinitions缓存中该beanName的合并缓存
//清除的方式是将stale属性设置为true,让BeanDefinition可以重新合并
clearMergedBeanDefinition(beanName);
//beanName添加到alreadyCreated缓存中
this.alreadyCreated.add(beanName);
}
}
}
}
6.4 isDependent是否有DependsOn依赖
isDependent方法用于判断第二个参数dependentBeanName对应的bean是否DependsOn依赖(第一个参数beanName对应的bean以及所有依赖beanName的bean)。
在doGetBean方法中,所调用的isDependent方法的第一个参数beanName对应的bean是DependsOn依赖第二个参数dependentBeanName对应的bean的(并且是通过depends-on属性或者@DependsOn注解)。因此这里的isDependent方法是被用来判断是否存在DependsOn循环依赖。如果isDependent方法返回true,那么说明存在DependsOn的循环依赖,Spring无法解决这种通过depends-on属性或者@DependsOn注解造成的循环依赖,因此下面直接抛出异常。
/**
* DefaultSingletonBeanRegistry的属性
* beanName到依赖该bean的beaName的set集合映射的map缓存
* bean之间的依赖关系的缓存,比如depends-on属性、@DependsOn注解、@Autowired的依赖、自动注入的依赖等
*/
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/**
* DefaultSingletonBeanRegistry的方法
* <p>
* dependentBeanName对应的bean是否依赖beanName对应的bean
*
* @param beanName 要检查的beaName
* @param dependentBeanName 依赖 beaName
*/
protected boolean isDependent(String beanName, String dependentBeanName) {
//加锁
synchronized (this.dependentBeanMap) {
//调用另一个isDependent方法
return isDependent(beanName, dependentBeanName, null);
}
}
/**
* DefaultSingletonBeanRegistry的方法
*
* @param beanName 要检查的beaName
* @param dependentBeanName 依赖的 beaName
* @param alreadySeen 临时集合,保存已经检查过beanName的set集合
* @return 是否依赖
*/
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
//如果alreadySeen不为null,并且不包含当前beanName,返回false
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
//确定原始名称,将别名解析为规范名称。
String canonicalName = canonicalName(beanName);
//从dependentBeanMap缓存中获取canonicalName对应的值,即依赖canonicalName的dependentBeans集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
//如果dependentBeans为null
if (dependentBeans == null) {
//返回false,表示dependentBeanName不依赖beanName
return false;
}
//如果dependentBeans集合包含dependentBeanName
if (dependentBeans.contains(dependentBeanName)) {
//返回true,表示dependentBeanName不依赖beanName
return true;
}
//遍历dependentBeans集合
for (String transitiveDependency : dependentBeans) {
//如果alreadySeen为null,那么新建set集合
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
//添加该beanName
alreadySeen.add(beanName);
//递归调用isDependent方法,传递每一个transitiveDependency,递归的校验
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
//如果有一个满足,那么返回true
return true;
}
}
//循环递归调用完毕还是没有返回,那么返回false
//表示dependentBeanName不依赖 beanName对应的bean以及所有依赖beanName的bean
return false;
}
6.5 registerDependentBean注册DependsOn依赖缓存
registerDependentBean方法用于将两个bean之间的DependsOn依赖关系添加到缓存中,这里有两个缓存,不要搞混淆了:
1 dependentBeanMap:beaName到依赖该bean的beaName的set集合映射的map缓存;
2 dependenciesForBeanMap:beaName到该bean依赖的beaName的set集合映射的map缓存。
举个例子,如果A DependsOn B,那么dependentBeanMap中存储的就是B -> A的映射,而dependenciesForBeanMap中存储的就是A -> B的映射。实际上depends-on属性、@DependsOn注解、基于注解的@Autowired、@Inject、@Resource等自动注入注解、基于XML的byType、byName等自动注入模式……等等存在的依赖关系都会注入到这两个缓存中(后面的文章会讲到)。因此可能存在由于自动注入注解或者自动注入模式造成的两个bean相互依赖,但是,前面说过了,Spring不允许通过depends-on属性或者@DependsOn注解造成的相互依赖。
//--------DefaultSingletonBeanRegistry的两个缓存属性--------
//--------depends-on属性或者@DependsOn注解的支持,甚至其他自动注入注解比如@Autowired的依赖也会加入--------
/**
* bean name到依赖该bean的bean name的set集合映射的map缓存
*/
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/**
* bean name到该bean依赖的bean name的set集合映射的map缓存
*/
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
/**
* 注册给定 bean 的依赖 bean关系到dependentBeanMap中,在销毁给定的 bean 之前销毁。
*
* @param beanName beanName
* @param dependentBeanName 依赖beanName的dependentBeanName
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
//确定原始名称,将别名解析为规范名称。
String canonicalName = canonicalName(beanName);
//加锁
synchronized (this.dependentBeanMap) {
//如果dependentBeanMap中不存在canonicalName的key,那么将一个新建的LinkedHashSet作为value存入并返回
//computeIfAbsent是Java8的新方法
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
//如果dependentBeans添加dependentBeanName失败,表示依赖关系已经存在那么直接返回
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
//加锁
synchronized (this.dependenciesForBeanMap) {
//如果dependenciesForBeanMap中不存在dependentBeanName的key,那么将一个新建的LinkedHashSet作为value存入并返回
//computeIfAbsent是Java8的新方法
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
//dependenciesForBean添加canonicalName
dependenciesForBean.add(canonicalName);
}
}
6.6 beforePrototypeCreation、afterPrototypeCreation原型bean创建回调
在创建原型bean之前,会调用beforePrototypeCreation方法,用于将对应的beanName存入当前线程的Threadlocal类型的缓存prototypesCurrentlyInCreation中,表示正在创建该beanName的原型实例。
在创建原型bean完毕或者抛出异常之后,会调用afterPrototypeCreation方法,用于将对应的beanName从当前线程的Threadlocal类型的缓存prototypesCurrentlyInCreation中移除。
如果只有一个原型bean,那么存入的value就是一个String类型的beanName;如果当前线程正在创建多个,那么存入的value就会转换为一个HashSet类型的beanName集合。
/**
* 当前正在创建中的原型 bean 的名称。ThreadLocal对象
*/
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");
/**
* 在原型bean实例创建之前进行回调
* 默认实现是将当前原型beanName注册到当前正在创建的bean缓存prototypesCurrentlyInCreation中
*
* @param beanName 即将创建的原型bean的名称
*/
@SuppressWarnings("unchecked")
protected void beforePrototypeCreation(String beanName) {
//获取当前线程正在创建的原型beanName
Object curVal = this.prototypesCurrentlyInCreation.get();
/*如果curVal为null*/
if (curVal == null) {
//那么设置值为当前beanName
this.prototypesCurrentlyInCreation.set(beanName);
}
/*
* 否则,如果curVal属于String,那么转换为set集合用于存放多个beanName
*/
else if (curVal instanceof String) {
//新建set集合
Set<String> beanNameSet = new HashSet<>(2);
//添加原值
beanNameSet.add((String) curVal);
//添加新值
beanNameSet.add(beanName);
//值设置为该集合
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
/*
* 否则,如果表示curVal属于set集合
*/
else {
//强制转型
Set<String> beanNameSet = (Set<String>) curVal;
//添加新值
beanNameSet.add(beanName);
}
}
/**
1. 在原型bean实例创建之后进行回调
2. 默认实现将原型标记为不在创建中,即从当前正在创建的bean缓存prototypesCurrentlyInCreation中移除
3. 4. @param beanName 已创建的原型bean的名称
*/
@SuppressWarnings("unchecked")
protected void afterPrototypeCreation(String beanName) {
//获取当前线程正在创建的原型beanName
Object curVal = this.prototypesCurrentlyInCreation.get();
/*
* 如果curVal属于String
*/
if (curVal instanceof String) {
//直接移除当前线程的ThreadLocal键值对即可
this.prototypesCurrentlyInCreation.remove();
}
/*
* 否则,如果表示curVal属于set集合
*/
else if (curVal instanceof Set) {
//强制转型
Set<String> beanNameSet = (Set<String>) curVal;
//从集合中移除该beanName
beanNameSet.remove(beanName);
//如果移除之后集合为为空,那么直接移除当前线程的ThreadLocal键值对
if (beanNameSet.isEmpty()) {
this.prototypesCurrentlyInCreation.remove();
}
}
}
6.7 getSingleton获取单例对象
doGetBean的核心方法。如果该bean属于单例类型,那么调用getSingleton方法获取单例对象。
- 首先会从单例缓存singletonObjects中判断给定beanName的缓存是否存在,如果存在就直接获取并返回了。
- 如果缓存不存在,那么就会 调用singletonFactory.getObject()方法获取新的单例bean实例。Spring 5之后,singletonFactory对象就是传递的一个lambda对象(在doGetBean方法中可以看见getSingleton方法的调用),它的getObject方法实际上就是调用的createBean方法,该方法是创建实例的核心方法。
- 在getObject方法之前,会调用beforeSingletonCreation回调方法,将对应beanName加入到singletonsCurrentlyInCreation缓存,表示该beanName的单例bean正在被创建。在getObject方法之后,会调用afterSingletonCreation回调方法,将对应beanName从singletonsCurrentlyInCreation缓存中移除,表示该beanName的单例bean已创建完毕,无论是创建成功还是失败。
- 如果创建新单例成功,则把beanName及其对相应的实例加入到相关单例缓存singletonObjects和registeredSingletons中,并从singletonFactories和earlySingletonObjects的单例bean缓存中移除该beanName对应的缓存。
//-----DefaultSingletonBeanRegistry的相关属性
/**
* bean name 到 bean instance 的单例bean实例缓存
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* 指示我们目前是否在销毁单例bean
*/
private boolean singletonsCurrentlyInDestruction = false;
/**
* suppressedExceptions集合属性用来记录相关异常信息,可用于关联抛出异常的相关原因
*/
@Nullable
private Set<Exception> suppressedExceptions;
/**
* DefaultSingletonBeanRegistry的方法
* <p>
* 返回给定名称的单例对象,如果尚未注册到缓存,则创建并注册新对象。
*
* @param beanName bean name
* @param singletonFactory 单例对象工厂,用于获取单例bean
* @return 注册的单例对象
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//加锁
synchronized (this.singletonObjects) {
//首先尝试直接从singletonObjects单例缓存中获取指定beanName的单例singletonObject
Object singletonObject = this.singletonObjects.get(beanName);
//如果singletonObject不为null,那么直接返回,如果为null,即缓存中不存在,那么需要创建并存入缓存
if (singletonObject == null) {
//如果目前正处于销毁bean的状态,那么不允许创建bean实例,直接抛出异常,默认为false
//前面讲的destroySingletons方法开始时就会将singletonsCurrentlyInDestruction置为true,销毁结束之后改为false
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//在单例bean实例创建之前进行回调
//默认实现是将当前单例beanName注册到当前正在创建的bean缓存singletonsCurrentlyInCreation中
beforeSingletonCreation(beanName);
//newSingleton标志位用于表示是否创建新实例成功,默认false
boolean newSingleton = false;
//suppressedExceptions集合属性用来记录相关异常信息
//先判断suppressedExceptions是否还没初始化
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
//如果没初始化,那么初始化该属性为一个LinkedHashSet集合
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//调用singletonFactory的getObject方法获取单例
//内部实际上就是调用lambda表达式的createBean方法
singletonObject = singletonFactory.getObject();
//标志着已经获取到了新实例
newSingleton = true;
} catch (IllegalStateException ex) {
//抛出异常之后,看singletonObject是否已经被创建了
//如果被创建了,那么继续后面的步骤,如果不是,那么抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
//如果recordSuppressedExceptions为true,表示属于当前方法
if (recordSuppressedExceptions) {
//遍历该集合,向此 bean 的创建异常添加相关异常原因
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
//抛出异常
throw ex;
} finally {
//如果recordSuppressedExceptions为true,表示属于当前方法
if (recordSuppressedExceptions) {
//suppressedExceptions再次置空
this.suppressedExceptions = null;
}
//在单例bean实例创建之后进行回调
//默认实现将单例标记为不在创建中,即从当前正在创建的bean缓存singletonsCurrentlyInCreation中移除
afterSingletonCreation(beanName);
}
//如果创建新单例成功
if (newSingleton) {
//把创建的单例bean加入到相关单例缓存
addSingleton(beanName, singletonObject);
}
}
//返回获取到的单例实例
return singletonObject;
}
}
/**
* 将给定的单例对象添加到此工厂的相关单例缓存中。
*
* @param beanName bean name
* @param singletonObject 单例对象
*/
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//添加到singletonObjects缓存中,从singletonFactories和earlySingletonObjects的单例bean缓存中移除
//相当于一个三级缓存,一个单例只能加入到其中一个单例bean缓存中,singletonFactories和earlySingletonObjects相当于中间状态的缓存
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
//添加到registeredSingletons缓存中,表示以注册实例的单例beanName缓存
this.registeredSingletons.add(beanName);
}
}
6.7.1 beforeSingletonCreation、afterSingletonCreation回调
在创建单例bean之前(singletonFactory.getObject()方法之前),会调用beforeSingletonCreation方法,用于将对应的beanName存入缓存singletonsCurrentlyInCreation集合中,表示正在创建该beanName的单例实例。如果添加成功,那么正常返回;如果添加失败,那说明此前已经有了该beanName缓存,可能是出现了构造器的循环依赖,即同一个bean实例被创建多次,Spring不允许构造器循环依赖,此时抛出异常。
在创建单例bean之后(singletonFactory.getObject()方法之后),会调用afterSingletonCreation方法,用于将对应的beanName从缓存singletonsCurrentlyInCreation集合中移除,表示创建该beanName的单例实例完毕,无论有没有创建成功。
//-----DefaultSingletonBeanRegistry的相关属性-----
/**
* 当前需要排除进行创建检查的 bean 的名称集合缓存
* 一般为空集合
*/
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/**
* 当前正在创建中的单例 bean 的名称集合缓存
*/
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/**
* DefaultSingletonBeanRegistry的方法
* <p>
* 在单例bean实例创建之前进行回调
* 默认实现是将当前单例beanName注册到当前正在创建的bean缓存singletonsCurrentlyInCreation中
*
* @param beanName 即将创建的单例的名称
*/
protected void beforeSingletonCreation(String beanName) {
//给定beanName是否是在排除创建检查的集合缓存中,如果是,那么什么也不做,方法结束;
//如果不是,那么尝试将给定beanName添加到singletonsCurrentlyInCreation的set集合中
//如果添加成功,那么正常返回;如果添加失败,那说明此前已经有了该beanName缓存,可能是出现了构造器的循环依赖,Spring不允许构造器循环依赖,此时抛出异常
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
/**
* DefaultSingletonBeanRegistry的方法
* <p>
* 在单例bean实例创建之后进行回调
* 默认实现将单例标记为不在创建中,即从当前正在创建的bean缓存singletonsCurrentlyInCreation中移除
*
* @param beanName 已创建的单例的名称
*/
protected void afterSingletonCreation(String beanName) {
//给定beanName是否是在排除创建检查的集合缓存中,如果是,那么什么也不做,方法结束;
//如果不是,那么尝试将给定beanName从singletonsCurrentlyInCreation的set集合中移除
//如果移除成功,那么正常返回判;如果移除失败,那说明当前beanName未在创建中
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
6.7.2 addSingleton加入到singletonObjects缓存
在对象完全创建完毕之后,该beanName以及对应的bean实例将被加入到singletonObjects缓存中,并且从singletonFactories、earlySingletonObjects缓存中移除对应的beanName的缓存。
因此实际上同一个beanName的实例只能存在于“三级缓存”中的某一个缓存中,因此所谓的“三级缓存”是不准确的,本人并不怎么喜欢这个说法!
/**
* 将给定的单例对象添加到此工厂的相关单例缓存中。
*
* @param beanName bean name
* @param singletonObject 单例对象
*/
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//添加到singletonObjects缓存中,从singletonFactories和earlySingletonObjects的单例bean缓存中移除
//相当于一个三级缓存,一个单例只能加入到其中一个单例bean缓存中,singletonFactories和earlySingletonObjects相当于中间状态的缓存
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
//添加到registeredSingletons缓存中,表示以注册实例的单例beanName缓存
this.registeredSingletons.add(beanName);
}
}
7 小结
finishBeanFactoryInitialization是一个非常重要的方法,该方法用于实例化所有非延迟加载的普通单例bean。本次主要介绍finishBeanFactoryInitialization方法的整体流程以及部分源码解析,主要有如下内容:
- SmartInitializingSingleton、FactoryBean 、SmartFactoryBean扩展点。
- getMergedLocalBeanDefinition获取合并的BeanDefinition,处理父类bean和子类bean。
- transformedBeanName和originalBeanName这两个转换beanName的方法,它们都会循环查找此前在前文讲解的aliasMap别名映射缓存:
- transformedBeanName用于转换、返回bean的名称,必要时删除全部&引用前缀,并解析别名为规范名称(id)。
- originalBeanName内部调用了transformedBeanName方法,区别就是如果原来name存在&前缀,那么返回的规范名称(id)同样会加上&前缀。
- getObjectForBeanInstance方法主要用于对FactoryBean的特殊处理:
- 如果是普通Bean则会直接返回传入的sharedInstance本身。
- 如果是FactoryBean则根据传递的参数beanName判断可能返回FactoryBean实例本身(beanName带有&前缀)或者FactoryBean.getObject方法返回的实例(beanName不带&前缀)。
- isDependent用于检测通过depends-on属性或者@DependsOn注解造成的循环依赖,Spring无法解决这种循环依赖,将会直接抛出异常。
- registerDependentBean则用于注册bean之间的依赖关系到dependentBeanMap和dependenciesForBeanMap缓存中。
- 实际上depends-on属性、@DependsOn注解、基于注解的@Autowired、@Inject、@Resource等自动注入注解、基于XML的byType、byName等自动注入模式……等等存在的依赖关系都会注入到这两个缓存中(后面的文章会讲到)。因此可能存在由于自动注入注解或者自动注入模式造成的两个bean相互依赖,但是,前面说过了,Spring不允许通过depends-on属性或者@DependsOn注解造成的相互依赖。
- 如果该bean属于singleton作用域类型,那么调用getSingleton方法获取单例对象,该方法是doGetBean的核心方法。
实际上,真正的创建bean实例的代码就是在getSingleton方法中(基于singleton作用域),是通过调用singletonFactory.getObject()方法获取新的单例bean实例的。前面说过,Spring 5之后,getSingleton方法的singletonFactory参数对象就是一个lambda对象,它的getObject方法实际上就是调用的createBean方法(在doGetBean方法中可以看见getSingleton方法的调用),因此createBean方法实际上才是创建实例的核心方法,可以,说本文到目前位置还没有接触到真正实例化bean的核心代码。
后续文章,我们将仔细讲解createBean方法,这个方法主要可分为bean的实例化和初始化这两个过程,并且涉及到了依赖注入(包括基于XML和注解的自动注入)以及各种回调方法。我们将至少分成两篇文章单独讲解该方法的源码,敬请期待。
相关文章:
https://spring.io/
Spring Framework 5.x 学习
Spring Framework 5.x 源码
Java8—一万字的Lambda表达式的详细介绍与应用案例
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!