【Spring源码分析】如何解决bean的循环依赖(一)

从这篇文章开始,我会用两篇文章来介绍spring是怎么解决循环依赖的。

【Spring源码分析】如何解决bean的循环依赖(二)

关于AbstractApplicationContext#refresh方法

refresh方法是spring中十分重要的方法,可以说整个ioc的精髓都在这个方法里了,今天我不对这个方法的调用链路进行介绍,这里只针对里面的每个方法进行一个简单的介绍,因为spring解决bean的循环依赖要从bean的创建过程进行讲起,所以有必要了解一下spring中创建bean的入口在哪里。后面我会找时间对每个方法进行详细的介绍(ps:每个方法其实都是很重要的)。

	@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();

			//准备bean工厂
			//一般是注册一些内部使用的bean
			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				//子类可以对bean工厂初始化进行修改
				// 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.
				/**
				 * 很重要,调用bean工厂中的所有BeanFactoryPostProcessor及其子类(BeanDefinitionRegistryPostProcessor)的实现
				 *
				 * --------------- 直接实现BeanDefinitionRegistryPostProcessor:
				 *
				 * ConfigurationClassPostProcessor 扫描配置类,基于ConfigurationClassBeanDefinitionReader
				 *
				 * --------------- 直接实现BeanFactoryPostProcessor:
				 *
				 * EventListenerMethodProcessor 处理@EventListener,注册成ApplicationListener
				 * DefaultEventListenerFactory EventListenerFactory默认实现,用于处理@EventListener,注册成ApplicationListener
				 *
				 * PropertyResourceConfigurer 属性配置基类
				 *      PropertyOverrideConfigurer 设置属性值,比如beanName.property=value
				 *      PlaceholderConfigurerSupport 处理占位符
				 *          PropertySourcesPlaceholderConfigurer 处理占位符
				 *          PropertyPlaceholderConfigurer 原有处理占位符方法,已过时
				 *              PreferencesPlaceholderConfigurer 原有处理占位符方法,已过时
				 *
				 * CustomAutowireConfigurer 自定义Qualifier注解
				 * DeprecatedBeanWarner 用于@Deprecated注解类的日志打印
				 * CustomEditorConfigurer 自定义bean属性编辑器,可以自定义属性的值
				 * AspectJWeavingEnabler
				 * CustomScopeConfigurer
				 */
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//往bean工厂中注册BeanPostProcessor
				/**
				 * BeanPostProcessor直接实现类:
				 * ServletContextAwareProcessor
				 * AdvisorAdapterRegistrationManager
				 * AbstractAdvisingBeanPostProcessor
				 *      AbstractBeanFactoryAwareAdvisingPostProcessor
				 *          MethodValidationPostProcessor
				 *          AsyncAnnotationBeanPostProcessor
				 *          PersistenceExceptionTranslationPostProcessor
				 * BootstrapContextAwareProcessor
				 * BeanValidationPostProcessor
				 * BeanPostProcessorChecker
				 * LoadTimeWeaverAwareProcessor
				 * ApplicationContextAwareProcessor
				 *
				 * BeanPostProcessor子接口:
				 * ------------------- MergedBeanDefinitionPostProcessor ------------ 处理合并bd
				 * JmsListenerAnnotationBeanPostProcessor
				 * ScheduledAnnotationBeanPostProcessor
				 * RequiredAnnotationBeanPostProcessor
				 * InitDestroyAnnotationBeanPostProcessor
				 *      CommonAnnotationBeanPostProcessor
				 * AutowiredAnnotationBeanPostProcessor
				 * ApplicationListenerDetector
				 * PersistenceAnnotationBeanPostProcessor
				 *
				 * ------------------- InstantiationAwareBeanPostProcessor ------------ 实例化前后的处理,处理属性
				 * ImportAwareBeanPostProcessor                 处理ImportRegistry
				 * AutowiredAnnotationBeanPostProcessor         处理@Autowired@Value@Inject
				 * CommonAnnotationBeanPostProcessor            处理@PreDestroy@PostConstruct@Resource@WebServiceRef等注解
				 * PersistenceAnnotationBeanPostProcessor
				 * RequiredAnnotationBeanPostProcessor
				 *
				 * ------------------- SmartInstantiationAwareBeanPostProcessor  ------------  继承InstantiationAwareBeanPostProcessor,预测bean的类型,推断构造函数等
				 * ScriptFactoryPostProcessor
				 * RequiredAnnotationBeanPostProcessor          处理@Required
				 * AutowiredAnnotationBeanPostProcessor         推断构造函数
				 * InstantiationAwareBeanPostProcessorAdapter
				 * AbstractAutoProxyCreator
				 *      BeanNameAutoProxyCreator
				 *      AbstractAdvisorAutoProxyCreator
				 *          DefaultAdvisorAutoProxyCreator
				 *          AspectJAwareAdvisorAutoProxyCreator
				 *              AnnotationAwareAspectJAutoProxyCreator
				 *          InfrastructureAdvisorAutoProxyCreator
				 *
				 * ------------------- DestructionAwareBeanPostProcessor ------------  bean销毁前的处理
				 * ScheduledAnnotationBeanPostProcessor
				 * SimpleServletPostProcessor
				 * InitDestroyAnnotationBeanPostProcessor
				 * CommonAnnotationBeanPostProcessor
				 * ApplicationListenerDetector              监听器检测
				 * PersistenceAnnotationBeanPostProcessor
				 */
				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.
				//todo 重要,实例化所有非懒加载的bean
				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();
			}
		}
	}
复制代码

prepareRefresh()

这个方法主要是初始化spring内部使用到的组件,主要包括:

  • 1、设置一些标志变量,比如是否关闭、是否活动
  • 2、initPropertySources(),初始化环境属性
  • 3、获取环境,为空的话则进行创建(StandardEnvironment)
  • 4、验证必要的一些环境属性
  • 5、初始化监听器

obtainFreshBeanFactory()

用于获取bean工厂,方法内部依次调用refreshBeanFactory()和getBeanFactory(),refreshBeanFactory()是刷新bean工厂的,子类实现,其中一个实现的子类是GenericApplicationContext,该子类在实现中设置序列化标志位;getBeanFactory()是获取bean工厂对象,子类实现,在GenericApplicationContext中获取的是DefaultListableBeanFactory类型的bean工厂。

prepareBeanFactory(beanFactory)

此方法是准备bean工厂,主要是注册一些spring内部使用的bean,包括ApplicationContextAwareProcessor、Environment相关的bean、设置忽略依赖的接口等。

postProcessBeanFactory(beanFactory)

这个方式可以让子类对bean工厂进行修改,保留了bean工厂子类的对于bean工厂的扩展能力。

invokeBeanFactoryPostProcessors(beanFactory)

这个方法很重要,spring会调用bean工厂中的所有BeanFactoryPostProcessor及其子类(BeanDefinitionRegistryPostProcessor)的实现。至于BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor是什么,有什么作用,读者可以自行去了解,这里我简单介绍一下spring使用这两个接口都做了什么,比如配置类的扫描是使用ConfigurationClassPostProcessor实现的,@EventListener注解的解析,使用的是EventListenerMethodProcessor实现的,这两个类都是BeanFactoryPostProcessor及其子类的实现类,还有很多类,其他的我就不介绍了,后面会有文章来做详细的介绍这个方法和这两个接口的作用。

registerBeanPostProcessors(beanFactory)

从方法的命名上可以看出,这个方法主要是往bean工厂中注册BeanPostProcessor的。BeanPostProcessor是spring中举足轻重的一个钩子接口,很多人翻译为bean后置处理器。在spring内部,实现bean类型推测、推断bean的构造函数、处理@Autowired、@Value和@Inject注解,还有一个重量级的功能,spring aop,都是基于BeanPostProcessor及其子类提供的能力进行实现的,同时作为开发者,也可以基于BeanPostProcessor及其子类提供的能力,在spring中对bean进行相关的扩展处理。上面的代码中我也对spring内部BeanPostProcessor的实现类做了一个整理,也标注了一些类的主要功能,读者可以自己找感兴趣的部分进行更深入地了解。

initMessageSource()与initApplicationEventMulticaster()

initMessageSource()方法是用于初始化MessageSource的,initApplicationEventMulticaster()方法是初始化ApplicationEventMulticaster的。

onRefresh()与registerListeners()

onRefresh()方法由子类实现,可以在bean初始化之前做一些额外的工作,这是spring模板方法设计模式的一个具体体现,当然,还有spring中还有很多地方运用这种模式。registerListeners()方法是往容器中注册监听器。

finishBeanFactoryInitialization(beanFactory)

这个方法是完成spring容器中所有非懒加载的bean的创建。这个方法很重要,里面涉及到了bean的实例化、aop代理、还有各种钩子函数的回调(比如BeanPostProcessor及其子类的回调)等。spring解决bean的循环依赖也在其中。

finishRefresh()

此方法是完成容器的刷新,主要包括LifecycleProcessor接口的回调、发布ContextRefreshedEvent事件等。

获取bean的入口-AbstractBeanFactory#getBean

刚才有讲到,spring中创建bean的入口是finishBeanFactoryInitialization(beanFactory)方法,这个方法是内部会调用beanFactory.preInstantiateSingletons()方法,这个方法就是spring创建非懒加载的bean的入口,最终会调用AbstractBeanFactory#getBean方法,我们来看看AbstractBeanFactory#getBean的具体代码:

        @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.
		//所有bd的名称
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			//合并bd
			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);
				}
			}
		}
        }
复制代码

可以看到,方法内部获取了spring容器中的所有bean定义的名称集合beanDefinitionNames,这里忽略FactoryBean的处理,最终会针对每一个bean去调用getBean方法,而这个方法就会从容器中去获取bean,那么在spring内部,对于获取bean是怎么处理的呢?我们接着往下看。

        @Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
复制代码
        protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//转换name
		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 {
			......
                        
			try {
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}

				//如果执行了markBeanAsCreated,则会重新合并bean
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				//合并bd不能是抽象的
				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 {
							//创建依赖的bean
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				//todo 重要:单例bean创建
				//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);
				}
                                
                                ......
			}
			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);
	}
复制代码

上面两段代码就是getBean内部调用doGetBean方法的具体实现,可以看出实现是比较复杂的,但是我在代码中标志了三个关键点,这三个地方就是获取与创建bean的关键节点,接下来我具体的来说说。

关键点一-获取bean,DefaultSingletonBeanRegistry#getSingleton(beanName)

关键点一,就是从容器的缓存中去拿bean,如果拿到了,就直接返回了。我们来看看这个从缓存中拿bean的方法具体长什么样:

        @Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}
复制代码
        @Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
                //《第一步》
		//先从singletonObjects获取
		Object singletonObject = this.singletonObjects.get(beanName);
		//如果singletonObject中没有,todo 并且当前bean正在创建
		//第一次进来的时候,是不会在正在创建的set中的
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//从earlySingletonObjects获取
                        //《第二步》
			singletonObject = this.earlySingletonObjects.get(beanName);
			//如果earlySingletonObjects获取为空,并且允许创建早期的bean
			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) {
							//从singletonFactories中获取
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
                                                                //《第三步》
								//创建对象
								singletonObject = singletonFactory.getObject();
								//创建早期bean
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}
复制代码

从代码中可以看出,spring使用了三个map来存储bean,第一个是singletonObjects,第二个是earlySingletonObjects,第三个是singletonFactories,这里估计你就会有疑问了,为什么要用三个map来存储呢,用一个可以吗,用两个可以吗?带着疑问,我们接着往下读。

我在代码中关键节点的地方标注了步骤,接下来我们来仔细分析一下

第一步 首先从singletonObjects中去获取,如果获取到的singletonObject不等于null,if(singletonObject == null && isSingletonCurrentlyInCreation(beanName)) 这个判断就不会进,如果singletonObject等于null,则需要判断isSingletonCurrentlyInCreation(beanName)的值 ,那么这个方法是干什么的呢,我们来看看:

        public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}
复制代码

其实这个方法就是判断是否bean在singletonsCurrentlyInCreation集合中,那么singletonsCurrentlyInCreation是干什么的呢?这个集合存储的是当前spring中正在进行创建的bean的集合,也就是说,如果一个bean正在创建,它会被添加到这个集合中,那bean是什么时候被添加进这个集合中的呢?后面的内容我会进行说明。其实读到这里已经很清楚了,第一次进入的时候,这个bean并不存在于singletonsCurrentlyInCreation集合中,也就是这个条件不会进入,最后singletonObject返回null。那如果bean存在singletonsCurrentlyInCreation集合中呢,这里我们不妨猜想一下,什么情况下这个bean会出现在集合中,其实就只有一种情况,就是在后面的代码流程中,spring会将这个bean添加进singletonsCurrentlyInCreation集合中,然后又走了一次这个bean的getBean过程,这个时候if(singletonObject == null && isSingletonCurrentlyInCreation(beanName)) 这个判断就会进入,那这里我们就假设这个条件成立,接着往下分析第二步。

第二步 这一步是从earlySingletonObjects这个map中去获取,根据获取的singletonObject,来判断是否进入条件 if(singletonObject == null && allowEarlyReference) ,这里有个参数allowEarlyReference,这个参数是从getSingleton方法中传进来的,意思是是否允许获取早期引用,这里传入的true,所以这个条件会进入。在标记了第三步这一行之前的代码,是spring对于获取bean做的double check lock的优化,可以先不用管。那么接下来我们来看一下第三步做了啥。

第三步 从singletonFactories中获取一个ObjectFactory对象,然后调用getObject获取singletonObject,并且singletonObject将put到earlySingletonObjects中。这里需要说明一下,ObjectFactory是一个工厂方法模式接口,可以产生一个对象,那么这个ObjectFactory对象是什么时候被put到singletonFactories中的呢?接着往下读。

关键点二-获取bean,DefaultSingletonBeanRegistry#getSingleton(beanName,objectFactory)

关键点二,这个方法用于获取单例bean,我们来看下具体的实现代码:

        public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			//先从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 + "'");
				}

				//添加当前bean到正在创建的set集合中
				beforeSingletonCreation(beanName);

				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//这里创建bean,这里是调用 createBean 方法
					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;
					}

					//当前bean从正在创建的set集合中移除
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					//添加bean到singletonObjects,并从singletonFactories和earlySingletonObjects中移除
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}
复制代码

这里面有几个比较关键的代码,我具体的进行分析一下。

beforeSingletonCreation方法

我们先来看一下beforeSingletonCreation方法的内部实现:

        protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}
复制代码

可以看出,这个方法是将bean添加进singletonsCurrentlyInCreation集合中的,也就是回答上面bean是什么时候被添加进singletonsCurrentlyInCreation集合中的问题了。inCreationCheckExclusions需要说明一下,指的是排除正在创建的bean,也就是如果一个bean在这个集合中,则说明这个bean不能被加入到singletonsCurrentlyInCreation集合中,一个bean一般情况下是不在inCreationCheckExclusions中的,所以是可以被加入到singletonsCurrentlyInCreation中的。

singletonObject = singletonFactory.getObject()

singletonFactory.getObject()执行的是什么,执行的是AbstractAutowireCapableBeanFactory#createBean方法,这个是后面要讲的,也就是创建bean的过程。singletonFactory.getObject()的返回值,也就是创建的bean,赋值给singletonObject。

afterSingletonCreation(beanName)方法

	protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}
复制代码

afterSingletonCreation方法其实就是将bean从正在创建的集合singletonsCurrentlyInCreation移除,表示这个bean已经创建完毕了。

addSingleton(beanName, singletonObject)方法

	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到singletonObjects,并从singletonFactories和earlySingletonObjects中移除相关的bean,这时这个bean已经是一个完整的bean,保存于singletonObjects中,如果通过getBean获取的话,可以直接从singletonObjects中获取,无需进行创建了。

小结

通过上面的分析,我在这里做一个简单的小结,巩固一下之前的分析。这里我分步骤来进行介绍:

  • 1、spring通过getBean方法获取bean,getBean方法内部实际调用的是doGetBean方法;
  • 2、doGetBean方法内部我列了三个比较关键的地方,如下的代码段:
//关键点一
//从缓存中去拿
Object sharedInstance = getSingleton(beanName);

......

//单例bean创建
//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);
}

......

复制代码

我们再来简单的回顾一下这几个关键点:

关键点一,通过getSingleton(beanName)方法从spring容器中获取这个bean,如果得到的sharedInstance不为null,就可以返回了,而getSingleton(beanName)方法内部使用了三个map来处理的bean的获取。首先从singletonObjects中获取,如果能拿到,就不用进行下面的流程了;如果没有从singletonObjects中获取到,然后这个bean又存在于singletonsCurrentlyInCreation集合中,就从earlySingletonObjects中获取;如果也没有获取到,并且allowEarlyReference=true,这时就从singletonFactories中获取一个和这个bean关联的singletonFactory,通过调用singletonFactory.getObject()方法获取一个对象,然后返回出去。注意这里有两个重要的地方,singletonsCurrentlyInCreation和allowEarlyReference,singletonsCurrentlyInCreation表示spring容器中正在进行创建的bean,allowEarlyReference表示是否获得早期对象的引用,如果是true,就会从通过singletonFactory.getObject()得到早期对象引用,然后put到earlySingletonObjects中。

关键点二,DefaultSingletonBeanRegistry#getSingleton(beanName,objectFactory)方法,方法内部有几处关键的地方:

  • beforeSingletonCreation方法,将bean添加进singletonsCurrentlyInCreation集合中,也就是正在创建的bean的集合
  • singletonObject = singletonFactory.getObject(),创建bean,实际通过lamada表达式调用了AbstractAutowireCapableBeanFactory#createBean方法
  • afterSingletonCreation(beanName)方法,其实就是将bean从正在创建的集合singletonsCurrentlyInCreation移除
  • addSingleton(beanName, singletonObject)方法,作用是添加bean到singletonObjects,并从singletonFactories和earlySingletonObjects中移除

通过对关键点一和关键点二的分析,我们对getBean的整个逻辑流程有了个比较清楚的了解了,接下来我们来看看关键点三,AbstractAutowireCapableBeanFactory#createBean方法的内部逻辑,了解bean的创建过程。

关键点三-创建bean,AbstractAutowireCapableBeanFactory#createBean

createBean方法是用于创建bean的,下面是主要的代码:

        @Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
                        
                ......
		
		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                        //关注点一
			//可以返回代理对象
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
                        //关注点二
			//创建bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}
复制代码

我在上面的代码中标注了两个关注点,我们后面主要介绍关注点二。关注点一这处代码,是可以在实例化前bean的时候,得到bean的对象的,然后返回。我们看下这一处的代码吧:

@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		//beforeInstantiationResolved是true时候会进入分支,默认是null
		//第一次肯定会进这个判断分支,因为是null
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			//实现了postProcessBeforeInstantiation方法只有:
			//1、AbstractAutoProxyCreator
			//2、CommonAnnotationBeanPostProcessor(空实现)
			//3、ScriptFactoryPostProcessor
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					//回调InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						//回调BeanPostProcessor.postProcessAfterInitialization()方法
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
复制代码

我在代码中加上了部分注释,可以看到内部其实分别回调了回调InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法和回调BeanPostProcessor.postProcessAfterInitialization()方法。在spring内部,InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()实现有AbstractAutoProxyCreator、CommonAnnotationBeanPostProcessor和ScriptFactoryPostProcessor,CommonAnnotationBeanPostProcessor内部是个空实现,我们主要关注AbstractAutoProxyCreator。AbstractAutoProxyCreator是spring aop框架中十分关键的base类,它的子类实现了处理bena并进行代理对象生成,后面我会有具体的文章介绍aop相关的源码。

doCreateBean方法

接着我们来看关注点二的代码,这里其实就是在创建bean了,接下来我们来看看doCreateBean方法具体的实现:

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			//从未完成的factoryBean缓存中获取bean
			//todo 这里针对factoryBean
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//创建bean实例,这里比较重要的是推断构造函数
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		//这里是根据构造函数推断出来的bean,还不成熟
		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 {
					//这里调用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()方法,处理合并bd
					//也可以使用合并bd的信息做一些事情
					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.
		//暴露一个对象工厂,并添加到singletonFactories map中
		//比如A,是单例的,也允许循环依赖,并且在beforeSingletonCreation方法中已经添加到正在创建的bean列表中
		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");
			}
			//这里添加的对象工厂会调用SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference()方法
			//只有 AbstractAutoProxyCreator 实现
			//这里可以对初始化出来的bean进行处理
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			//填充属性
			populateBean(beanName, mbd, instanceWrapper);
			//初始化bean
			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) {
			//获取早期引用,不存在循环依赖的时候,earlySingletonReference是null
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				//如果exposedObject和bean相等,只有两种情况:
				//1、两个都是代理对象,这时earlySingletonReference可能是代理对象
				//2、两个都是源对象,这时earlySingletonReference可能是代理对象
				//所以为了统一,这里直接赋值,
				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;
	}
复制代码

从上面的代码可以看出,doCreateBean方法内部还是很复杂的,接下来我会分段介绍,逐步拆解它的实现机制。

createBeanInstance方法

                // Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			//从未完成的factoryBean缓存中获取bean
			//todo 这里针对factoryBean
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//创建bean实例,这里比较重要的是推断构造函数
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		//这里是根据构造函数推断出来的bean,还不成熟
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
复制代码

上面的代码主要是通过createBeanInstance方法创建bean的实例,这时的bean还不成熟,还需要经过后续的初始化过程,成为一个可以真正使用的bean。createBeanInstance方法是比较重要的,比如bean的推断构造函数的过程,就是发生在这个方法中。

earlySingletonExposure与DefaultSingletonBeanRegistry#addSingletonFactory

                // Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		//暴露一个对象工厂,并添加到singletonFactories map中
		//比如A,是单例的,也允许循环依赖,并且在beforeSingletonCreation方法中已经添加到正在创建的bean列表中
		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");
			}
			//这里添加的对象工厂会调用SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference()方法
			//只有 AbstractAutoProxyCreator 实现
			//这里可以对初始化出来的bean进行处理
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
复制代码

上面这一段代码,其实就做了一个事情,往singletonFactories map中添加一个ObjectFactory对象,ObjectFactory对象内部会调用getEarlyBeanReference方法。

首先获取一个bool值earlySingletonExposure,如果bean是单例的、allowCircularReferences=true、并且当前bean正在创建bean的集合singletonsCurrentlyInCreation中,这个值就是true。bean是单例的,限制了bean的作用域,也就是说原型等其他作用域的bean是不会有关联的ObjectFactory对象的;allowCircularReferences参数是一个成员字段,默认是是true,表示是否允许循环依赖,这个值是可以设置的,通过setAllowCircularReferences方法设置,也就是说开发者可以手动关闭这个值,也就关闭了循环依赖的功能;singletonsCurrentlyInCreation集合前面已经详细的介绍过了,这里就不做过多的说明了。

earlySingletonExposure的值一般都是true,所以会进入后面的判断逻辑中,我们来看看addSingletonFactory方法做了什么:

        protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}
复制代码

可以看到,其实就是往singletonFactories map中添加一个ObjectFactory对象,这里也回答了ObjectFactory对象是什么时候被put到singletonFactories中的问题了。

populateBean方法

接下来会走bean的属性填充的过程:

        //填充属性
        populateBean(beanName, mbd, instanceWrapper);
复制代码

上述代码中,可能会出现循环依赖了,比如A依赖B,B依赖A,当对A进行属性填充的时候,发现了B这时就会走B的创建过程,然后走到B的populateBean方法,这时又发现了A,这时就出现了循环依赖了。那么spring是怎么处理的呢,我会第二篇文章详细的说明。

initializeBean方法

        //初始化bean
        exposedObject = initializeBean(beanName, exposedObject, mbd);
复制代码
        protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
复制代码

可以看到,initializeBean内部其实就是对一些钩子函数的回调,invokeAwareMethods是对Aware接口的回调,applyBeanPostProcessorsBeforeInitialization方法是对BeanPostProcessor#postProcessBeforeInitialization方法的回调,invokeInitMethods方法是对InitializingBean#afterPropertiesSet的回调,applyBeanPostProcessorsAfterInitialization方法是对BeanPostProcessor#postProcessAfterInitialization的回调,所以我们可以开发自己的InitializingBean、Aware接口,实现一定的功能,然后交于spring回调,这些接口也是spring扩展比较核心的接口;比如spring中强大的aop框架,就基于BeanPostProcessor#postProcessAfterInitialization进行了实现。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享