Spring bean 加载过程简要分析与循环依赖解决

何言 2021年08月18日 151次浏览

SpringContext

Spring 上下文是一系列组件的集合,包括了一个 Spring 应用运行期间和 Spring 所有有关的东西,包括 bean 工厂,原料扫描器,原料加载器等组件:

image20210813204128421.png

其中 BeanFactory 负责根据原料创建管理 Bean 。而其他组件负责提供原料,后置处理等操作 。

包括我们创建的 bean,也包含其中 。当我们使用 Spring framework 的时候,我们需要写出以下代码:

public static void main(String[] args) {
    ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
}

其中 AnnotationConfigApplicationContext 就是 Spring 上下文的一个实例,实际上还有许多使用其他配置的实例,但都实现了 ApplicationContext 接口 。

当我们执行这样一行代码时,Spring framework 的大致过程如下:

  • 初始化 bean 工厂 BeanFactory
  • 使用扫描和读取组件获取 Bean 定义
  • 工厂根据 定义 进行 Bean 的创建

接下来会大致分析一下各个流程的具体实现 。主要进行简单流程分析,重点分析 Spring Framework 在 EI 的过程中如何解决循环依赖的问题 。

具体流程在后面介绍,这里简单介绍一些基本组件 。

BeanFactory

BeanFactory 负责创建 ,管理 Bean,它持有单例池等对象 。可以说 Spring 的 IOC 功能很大程度就是在 BeanFactory 中实现 。

当我们调用 AnnotationConfigApplicationContext 的构造方法时,会转到其无参构造方法。同时因为 Java 的特性,这里同样会调用父类的无参构造方法,也就是 GenericApplicationContext 的构造方法:

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

可以看到将 beanFactory 组件赋值为 DefaultListableBeanFactory 实例 。也就是至少在该上下文中,其 BeanFactory 为该类型的。后面也会根据该类中的方法进行说明 。

在 DafaultListableBeanFactory 中有许多成员变量,其中有几个比较重要,当然为了将 Bean 与 Class 对应还有类似 其他的 Map 来加快效率,这里不列出:

	/** Map of bean definition objects, keyed by bean name. */
	/** <Bean 名字,Bean 定义> 用于储存定义 */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);


	// 以下为 父类 DefaultSingletonBeanRegistry 的成员变量

	// 三级缓存的,用于解决循环依赖

	/** Cache of singleton objects: bean name to bean instance. */
	/** 单例池,初始化后最终的 Bean 会存放在此 */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	/** 用于储存 ObjectFactory ,主要是为了处理类似 AOP 的动态代理 Bean 的创建*/
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	/** 用于储存只实例化但还没完成注入或正在进行依赖注入的 Bean */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

BeanDefinition

BeanDefinition 是一个接口,用来描述一个 Bean,我们可以看看类图:

image20210813205609068.png

可以看到,一个 BeanDefinition 储存了一个 Bean 的名字 (name),类型 (ResolvableType),是否懒加载 (isLazyInit) 等信息 。当一个上下文启动时,会根据配置扫描我们定义的 Bean,然后构造 BeanDefinition 对象放进工厂中,然后由 工厂 实现创建和管理 。

接下来我们看看 Spring bean 的加载过程 - 这里只分析单例类

AnnotationConfigApplicationContext 初始化

首先是我们调用的有参构造方法:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

可以看到有三条,首先是调用自身的无参构造方法,然后调用 register 将 配置类 自身进行注册,(这里的注册实际上指的是生成其定义放入工厂)。refresh 为根据工厂中存在的定义 来 进行 bean 的创建操作(如果是配置 Bean 也会在此时生成其定义)

实际上,当调用 this 的时候,this 中会先调用 super , 然后再套一层 super ,最终会按照以下流程执行:

  • AbstractApplicationContext : 将 resourcePatternResolver 赋值为 PathMatchingResourcePatternResolver 实例
  • GenericApplicationContext :将 beanFactory 赋值为 DefaultListableBeanFactory 实例(上面有代码)
  • AnnotationConfigApplicationContext:
    • 将 reader 赋值为 AnnotatedBeanDefinitionReader 实例,
    • 将 scanner 赋值为 ClassPathBeanDefinitionScanner 实例

比较简单,这里不给出代码,主要就是初始化上下文的各个组件 。

之后来到 register 方法,该方法会将传入的 配置类 对象传入 reader 的 register 方法,也就是来到 AnnotatedBeanDefinitionReader 中的 register 方法,实际上,该组件的作用就是分析一个类生成其定义并放到工厂中 :

// AnnotatedBeanDefinitionReader#register
public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}

// AnnotatedBeanDefinitionReader#registerBean
public void registerBean(Class<?> beanClass) {
    doRegisterBean(beanClass, null, null, null, null);
}

可以看到将传入的配置类一个一个传入 registerBean 方法,最终回来到 doRegisterBean 方法,这里是一个重点:

// AnnotatedBeanDefinitionReader#doRegisterBean
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
                                @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
                                @Nullable BeanDefinitionCustomizer[] customizers) {

    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    abd.setInstanceSupplier(supplier);
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }

    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

主要是获取一下类的名字,Scope,是否懒加载 等信息。最终封装成一个 BeanDefinitionHolder,BeanDefinitionHolder 持有 一个 BeanDefinition 与其 名字 与 昵称 。

然后调用 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); 方法:

// BeanDefinitionReaderUtils.registerBeanDefinition
public static void registerBeanDefinition(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    
    /*核心*/
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

可以看到主要为 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 这一行语句,将 definitionHolder 中的 beanDefinition 与名字注册进传入的 registry ,这里 register 实际上是 AnnotatedBeanDefinitionReader 中的 register 对象,从上面的传入也可以看出,而该对象在 AnnotatedBeanDefinitionReader 构造方法中传入,而在 AnnotationConfigApplicationContext 中传入的 register 为 this,而 AnnotationConfigApplicationContext 中没有重写该方法,最终是来到 GenericApplicationContext 的 registerBeanDefinition 方法:

// GenericApplicationContext#registerBeanDefinition
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    throws BeanDefinitionStoreException {
    this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}

兜兜转转,来到 beanFactory 中的 该方法,因此最终来到 DefaultListableBeanFactory :

// DefaultListableBeanFactory#registerBeanDefinition
// 只保留核心
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    throws BeanDefinitionStoreException {

    // 是否存在该定义
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) { // 存在
        
        // 是否允许重写,不允许直接抛异常
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }
        // 根据情况打 Log
        else if (existingDefinition.getRole() < beanDefinition.getRole()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (logger.isInfoEnabled()) {
                logger.info("Overriding user-defined bean definition for bean '" + beanName +
                            "' with a framework-generated bean definition: replacing [" +
                            existingDefinition + "] with [" + beanDefinition + "]");
            }
        }
        else if (!beanDefinition.equals(existingDefinition)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Overriding bean definition for bean '" + beanName +
                             "' with a different definition: replacing [" + existingDefinition +
                             "] with [" + beanDefinition + "]");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Overriding bean definition for bean '" + beanName +
                             "' with an equivalent definition: replacing [" + existingDefinition +
                             "] with [" + beanDefinition + "]");
            }
        }
        // 执行至此,一定是允许重写的,直接覆盖
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        // 此时 Bean 创建是否已经开始,若已经开始,则需要加锁,同时进行一些同步操作
        // 主要是更新 beanDefinitionMap 与 beanDefinitionNames
        if (hasBeanCreationStarted()) { 
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            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;
                removeManualSingletonName(beanName);
            }
        }
        else {
            // Still in startup registration phase
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
}

我这里进行了一些删减,实际上就是对定义进行判断,如果已经被定义了,则根据是否允许覆盖来进行处理 。

否则则更新 beanDefinitionMap 与 beanDefinitionNames 两个容器,其中第一个是 刚刚的 名字与定义的 map ,第二个是一个名字的列表 。

此外,我们来看看 hasBeanCreationStarted 方法。该方法为 AbstractBeanFactory 中的方法

// AbstractBeanFactory#hasBeanCreationStarted 
protected boolean hasBeanCreationStarted() {
   return !this.alreadyCreated.isEmpty();
}

主要是判断 alreadyCreated 是否为空, alreadyCreated 是一个 Set<String>,储存了所有已经创建了 Bean 的 名字,如果这里有则表示已经开始创建了 。

那么什么时候会出现运行到这里而已经有创建的类呢?

实际上,根据刚刚的分析,在 register 这一步中,我们只是简单的 将 配置类,也就是 javaConfig 的定义放入 beanDefinitionMap,而真正根据 beanDefinitionMap 创建 bean 是在之后 refresh 阶段 。因此可以判断,javaConfig 会首先被创建为一个 bean,然后再根据其中的定义去获取新的 定义,进而创建新的类 。而那时也避免不了会有将 BeanDefinition 放入 beanDefinitionMap 的操作 。因此我们这里可以猜测之后 。当 Config bean 创建成功开始创建其定义的 bean 时,也会再次调用该方法 。

至此,register 过程就完毕,这里我们回顾一下,该阶段主要做一件事,就是将我们传入的 javaConfig 使用 reader 构造一个对应的 BeanDefinition 对象,然后放入 beanDefinitionMap。 至此我们也可以看出在 Spring framwork 内部,对于 bean register 的过程指的是将其 BeanDefinition 放入 BeanFactory 中 beanDefinitionMap 的过程。

refresh

接下来是 refresh 操作了,回顾一下刚刚的构造方法:

// AnnotationConfigApplicationContext#AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this(); // 实例化 reader beanFactory scanner 等组件
    register(componentClasses); // 使用 reader 获取 传入 config 类的 Definition 对象放入 beanFactory 中 beanDefinitionMap 对象
    refresh();
}

这里我们大概知道了 refresh 的作用了:根据 beanDefinitionMap 中的 definition 创建对应 bean,对于 config 的 bean,会同时注册其定义的新的 bean (注册的过程刚刚已经定义过了)。

接下来来看看该源码:

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

挺复杂的,其实主要是一个同步锁,然后调用了若干方法,其中我们要注意以下方法:


// 使用 工厂中 的 FactoryPostProcessors 责任链处理当前的 beanDefinition
invokeBeanFactoryPostProcessors(beanFactory);

// 创建 beanDefinitionMap 中剩余的 beanDefinition
finishBeanFactoryInitialization(beanFactory);

beanFactoryPostProcessors

是一个处理器,用于进行 defenition 的处理,使用了责任链模式,以下是其在 AbstractApplicationContext 中的定义 :

/** BeanFactoryPostProcessors to apply on refresh. */
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    return this.beanFactoryPostProcessors;
}

BeanFactoryPostProcessor 的定义如下:

@FunctionalInterface
public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

可以看到是一个方法接口,参数为 beanFactory 。

实际上,在 beanFactory 中 refresh 的时候,会将自己按照列表顺序依次传递给 BeanFactoryPostProcessor,并依靠他们实现 bean 的扫描等操作 。

而我们自己也可以定义自己的 BeanFactoryPostProcessor,只需要自己实现该接口,并将自己注册为 bean ,则在 invokeBeanFactoryPostProcessors 方法中会自动将我们 BeanFactoryPostProcessor 的 对象创建并放入 beanFactoryPostProcessors

来看看 invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

来到的是 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors

	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the bean factory post-processors apply to them!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
			// PriorityOrdered, Ordered, and the rest.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		beanFactory.clearMetadataCache();
	}

该方法很复杂,其实,这里的 PostProcessors 不只是我们确定的后置处理器,实际上,在刚刚启动的时候,beanFactoryPostProcessors 一般为空 。

除了 beanFactoryPostProcessors 的处理器外, 此处还会获取

// 直接在 beanFactory 中获取类型为 BeanDefinitionRegistryPostProcessor 的 bean
String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}

当调用 beanFactory#getBean 的时候,已经进入了创建过程,这里会判断 bean 是否已经创建,如果没创建则去 中 beanDefinitionMap 中获取 definition 并开始创建 。当发现其依赖新的 bean 的时候,会递归调用 。同时使用 缓存 解决循环依赖的问题 。这里之后会分析。

到这,我们一个 bean 都没创建,因此肯定会去 beanDefinitionMap 中寻找 BeanDefinitionRegistryPostProcessor 类型的并创建 。这里 BeanDefinitionRegistryPostProcessor 也是 BeanFactoryPostProcessor 的子类,不过具有更高的优先级。

总而言之,invokeBeanFactoryPostProcessors 做了以下事情:

  • 获取类型为 BeanDefinitionRegistryPostProcessor 类型的 bean
  • 将获取到的 BeanDefinitionRegistryPostProcessor 与 getBeanFactoryPostProcessors 获得的 列表一起排序
  • 依次调用方法进行消息处理

当然,这里为了解决循环调用,优先级等问题,做了许多处理,值得再 写一篇文章,这里就不深究了 。

而在 Spring framwork 中已经默认加入了一系列 BeanDefinitionRegistryPostProcessor 在 beanDefinitionMap 中,包括创建 config 的 beanDefinition , 并将其中指定的其他 beanDefinition(包括扫描和手动注册)生成并注册 。

因为主要为了分析循环依赖,因此这里不打算分析,直接点到为止 。

经过 一系列处理,在finishBeanFactoryInitialization 方法调用前,所有的 definition 都注册完毕,此时 beanDefinitionMap 已经存有所有我们指定的 bean 定义,但此时还未创建 (实际上有一些特殊的会提前创建,这里不做分析) 。因此 finishBeanFactoryInitialization 为最终从 beanDefinitionMap 中获取 beanDefiniton 并创建 bean 的方法 。

对 finishBeanFactoryInitialization 方法关键部分进行追踪,最终会来到 beanFactory#preInstantiateSingletons() 方法,而这里 最终会来到 DefaultListableBeanFactory 中该方法:

// DefaultListableBeanFactory#preInstantiateSingletons
@Override
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(
                            (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                            getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                       ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                getBean(beanName);
            }
        }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
                .tag("beanName", beanName);
            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
            smartInitialize.end();
        }
    }
}

代码比较多,涉及到 FactoryBean 等的处理,但关键部分在于 getBean(beanName); ,从名字来说,getBean 也就是 获取 bean 的意思 。而这里也可以用来创建。之后我们将分析该方法 。

getBean

接下来是我们分析的重点,也就是 getBean 方法 。也是解决循环依赖的核心,这里我们假设所有的 beanDefinitionMap 都获取好了,但是没有创建 。而我们调用 getBean 方法尝试获取 bean 。

在 BeanDefinitionRegistryPostProcessor 处理的时候并不会创建 config bean,只是创建其 definition 对象并根据我们的定义去扫描或创建新的 definition 并注册

在初始化过程中,当需要创建 bean 的地方,都会调用 getBean 的相关方法,当 bean 不存在则会再去创建 。也就是说,我们创建好上下文后调用的 getBean 方法和创建过程中的 bean 创建的方法实际上是调用同一个方法(顶层空壳方法不一定,但在 beanFactory 中是同一个),也就是我们现在来研究的方法。

继续刚刚的分析,这里 getBean 方法最终会来到 AbstractBeanFactory 中

// AbstractBeanFactory#getBean
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

来到 doGetBean:

protected <T> T doGetBean(
    String name,
    @Nullable Class<T> requiredType,
    @Nullable Object[] args,
    boolean typeCheckOnly)
    throws BeansException {

    String beanName = transformedBeanName(name);
    Object beanInstance;

    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            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 + "'");
            }
        }
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                    nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
        try {
            if (requiredType != null) {
                beanCreation.tag("beanType", requiredType::toString);
            }
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // Explicitly remove instance from singleton cache: It might have been put there
                        // eagerly by the creation process, to allow for circular reference resolution.
                        // Also remove any beans that received a temporary reference to the bean.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            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);
                }
            }
        }
        catch (BeansException ex) {
            beanCreation.tag("exception", ex.getClass().toString());
            beanCreation.tag("message", String.valueOf(ex.getMessage()));
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
        finally {
            beanCreation.end();
        }
    }

    return adaptBeanInstance(name, beanInstance, requiredType);
}

出去不关心的,实际上就是 getSingleton 的多次调用 。

先来看看第一次调用:

Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
    if (logger.isTraceEnabled()) {
        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 + "'");
        }
    }
    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

调用 getSingleton(String) 方法,获取到则直接返回,这里来到该方法:

@Override
@Nullable
public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                // Consistent creation of early reference within full singleton lock
                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) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

代码很多,主要逻辑如下:

  1. 判断一级缓存 (singletonObjects) 是否存在该对象,如果存在则返回,否则判断其是否在创建中(递归来的),如果不在创建中则返回 null,否则进入2
  2. 判断二级缓存 (earlySingletonObjects) 是否存在该对象,如果存在则返回,否则判断 allowEarlyReference 标记,如果不允许早期持有,则返回 null,否则进入3
  3. 加入同步锁,再次从 1 开始,但这次最后会来到 4
  4. 判断三级缓存 (singletonFactory) 是否存在该对象的工厂,如果存在则创建 bean 放入二级缓存并返回,否则进入 5
  5. 返回 null

其实该方法主要是为了三级缓存工作的,该方法用于获取早期对象,如果返回 null 则 doGetBean 会调用之后 创建 bean 的逻辑 。

加同步锁同时在锁中对 一级二级缓存进行判断是为了确保 ObjectFactory 的创建 bean 只会调用一次,当并发执行时,先获取锁的对象负责创建,后进入锁的对象会在二级缓存找到刚刚创建的对象。

第一次调用后判断是否拿到,如果拿到了则直接返回,如果拿不到则自己走之后的逻辑,注意以下地方:

String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                            "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        registerDependentBean(dep, beanName);
        try {
            getBean(dep);
        }
        catch (NoSuchBeanDefinitionException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                            "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
        }
    }
}

这里主要是获取用 @dependsOn 注解声明的依赖,然后调用 getBean 进行递归,因此使用 @dependsOn 的循环依赖 spring 无法解决,也可以看到这里直接抛出了异常 。

继续往后走

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
        }
    });
    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

因为我们只分析单例的,因此直接看到这里,这就是第二次调用 getSingleton,但这次调用的是另外一个重写,这里第二个参数是一个 ObjectFactory :

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            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 + "'");
            }
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

其实还是比较简单,首先在 一级缓存 中尝试获取,如果有则直接返回,否则先调用 beforeSingletonCreation 判断一下环境,比如当前是否在创建等,如果通过了则调用传入的 objectFactory 的 getObject() 方法获取对象,然后再 finally 中,如果创建成功了则调用 addSingletion 方法,来看看:

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);
    }
}

可以看到这里首先是一个同步锁,然后直接将其加入 一级缓存并在其他缓存中删除 。说明该 bean 以及创建好并且所有注入都处理好,但是在哪里处理的呢?

我们注意到在 doGetBean 中,

sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
        }
    });

传入的工厂中调用的 是 createBean 方法,该方法较为复杂,进行一些处理后会来到 AbstractAutowireCapableBeanFactory 中的 doCreateBean 方法:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    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;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    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));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        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);
        }
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                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.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

重点看下面两句:

// 创建 bean
Object bean = instanceWrapper.getWrappedInstance();

// 是否允许提前暴露引用
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));
}

可以看到首先实例化委托给了 instanceWrapper,实例化出来后,会判断是否允许提前暴露引用,如果允许,则会在三级缓存中加入一个工厂,该工厂会来到 getEarlyBeanReference(beanName, mbd, bean) 方法:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    // 判断是否需要进行代理等处理
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
            exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
        }
    }
    return exposedObject;
}

可以看到,这里有两种情况,直接返回对象,或进行一些动态代理等操作 。

至此,我们可以总结一下 getBean 的过程:(省略所有合法性检查)

  • 第一次调用 getSingleton 方法,在缓存中获取对象,从一到三依次判断,其中如果在三级缓存中,则调用工厂方法创建一个 bean 放入二级缓存
  • 如果第一次获取不到,则该 bean 还没创建,则第二次调用 getSingleton 方法,这里传入接口增加扩展性,也是在这里开始递归创建对象,因此当传入的接口执行完毕后,会直接执行 addSingleton 方法将对象放入一级缓存,因为递归执行到此没有异常说明该对象所有依赖都注入完毕。
  • 来到 doCreateBean 方法,这里将 bean 创建出来,然后将一个 () -> getEarlyBeanReference(beanName, mbd, bean) 的工厂放入三级缓存,这里会判断需要进行动态代理等操作

总结

至此,循环依赖分析完毕,分点总结:

  • spring 处理循环依赖只支持使用 @Autowired 注入的依赖,对于构造方法注入,则代码层面目前没有稳定解决方案 。
  • 其实对于解决循环依赖,只要一级缓存提前暴露引用就可以配合递归工作(实际上第一级 singletonObjects 直接就是单例池了,算啥缓存哟),Spring 要分成三级缓存个人认为是在规范方面考虑
    • 一级缓存中的对象一定是创建好的,并且所有依赖都注入完毕
    • 二级缓存中的对象是早期引用,并且一定是被循环引用过的创建中的对象会被放到二级缓存
    • 三级缓存中的是工厂,主要为调用 getEarlyBeanReference 的工厂,当被创建后会放入二级缓存,如果出现循环引用则会在第一次被引用时调用,如果存在动态代理等情况则在此时生成代理对象,否则直接返回原对象并放入二级缓存 。
  • 第三级依赖 singletonFactories 出现的本意不是解决循环依赖,而是为了支持 AOP 等操作(生成代理对象),而 Spring 有一个原则是尽量将生成动态代理的操作延后 。这才是 singletonFactories 最主要的目的 。
  • 实际上,循环依赖是程序设计的问题,一个健壮的系统就不应该出现循环依赖 。这也是 Spring 推荐使用构造函数注入的原因之一,此外,因为构造函数注入的变量能用 final 修饰,使用 final 修饰能保证不为空,也不会出现并发问题(如果使用 setter 注入则可能会出现并发状态下该对象正在构造中还没注入而你直接使用的情况)。当然 使用 final 可能会在构造方法中逃逸的问题,但几率很小。
  • 当一个对象需要被多次动态代理时,在使用 @Autowired 注入依赖 并且存在循环引用的时候可能会出现问题,因为刚刚的分析中三级缓存中的工厂只会执行一次(代码中也有使用锁),因此可能会出现代理失效等问题,其次,在使用工厂构造 bean 之后,spring 会检查构造的 bean 是否和原来的一致(刚刚代码中没有体现),在循环依赖时可能会出现误判而抛出异常。