Spring源码阅读之初始化"非懒加载bean"实例-3
0. 导读
写在前面的一点 “废话”,关于流程图的一点说明,有读者朋友反馈说之前的文章内容太干了,要是有点图文说明就更好了,经过博主仔细考虑之后,决定以流程图的方式加以适当配合说明,希望朋友们喜欢。(本文来自公众号:z小赵)
接着上篇文章,本文接着bean实例的创建过程,主要分为以下4部分
- getBean()流程分析
- getMergedLocalBeanDefinition()流程分析
- doCreateBean()流程分析
- getObjectForBeanInstance()流程分析
- 循环依赖解决方案剖析1.getBean() 流程总览
2.getBean() 源码分析
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
// Check with full lock now in order to enforce the same merged instance.
// Step1:从mergedBeanDefinitions缓存中获取mbd定义
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null) {
// Step2:如果当前BeanDefinition定义不存在父name
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
// Step2.1:BeanDefinition定义实现了RootBeanDefinition接口,拿当前BeanDefinition克隆一个mbd
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
// Step2.2:拿当前BeanDefinition定义创建一个新的RootBeanDefinition定义。
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
// Step3:获取父BeanName
String parentBeanName = transformedBeanName(bd.getParentName());
// Step3.1:父beanName和当前beanName不相同,使用父beanName创建mbd定义。
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
// Step3.2:使用父BeanFactory创建mbd定义
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// Step3.3:使用父BeanDefinition定义new一个mbd定义,然后在将BeanDefinition定义覆盖到mbd上。
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
// Step4:设置默认scope属性
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
// Step5:将创建出来的mbd定义放入mergedBeanDefinitions本地缓存
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
// Step6:返回mbd定义
return mbd;
}
}
3.getMergedLocalBeanDefinition() 码分析
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
// Check with full lock now in order to enforce the same merged instance.
// Step1:从mergedBeanDefinitions缓存中获取mbd定义
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null) {
// Step2:如果当前BeanDefinition定义不存在父name
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
// Step2.1:BeanDefinition定义实现了RootBeanDefinition接口,拿当前BeanDefinition克隆一个mbd
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
// Step2.2:拿当前BeanDefinition定义创建一个新的RootBeanDefinition定义。
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
// Step3:获取父BeanName
String parentBeanName = transformedBeanName(bd.getParentName());
// Step3.1:父beanName和当前beanName不相同,使用父beanName创建mbd定义。
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
// Step3.2:使用父BeanFactory创建mbd定义
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// Step3.3:使用父BeanDefinition定义new一个mbd定义,然后在将BeanDefinition定义覆盖到mbd上。
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
// Step4:设置默认scope属性
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
// Step5:将创建出来的mbd定义放入mergedBeanDefinitions本地缓存
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
// Step6:返回mbd定义
return mbd;
}
}
BeanDefinition定义转换成RootBeanDefinition定义。主要是两种方式,关于二者的区别读者朋友自行查阅相关说明。
- 一种是 clone 的方式
- 一种是 new 的方式
4.doCreateBean() 流程分析
5.doCreateBean() 源码分析
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// Step1:从缓存中获取
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// Step2:手动创建bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Step3:获取bean实例和对应的class
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// Step4:如果BeanPostProcessor还没有执行,则在此时执行一次bean后置处理器来修改mbd定义
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 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.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// Step5:第一步获取当前bean实例的依赖,如果没有则返回自己
// 第二步将获取到的bean实例添加到本地缓存中,正是通过这种方式解决了bean实例的循环依赖问题。
// 如果不能理解,文末提供例子在来说明。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// Step6:填充bean实例的属性
populateBean(beanName, mbd, instanceWrapper);
// Step7:初始化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) {
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 " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// Step8:将创建出来的bean实例注册到BeanFactory里面。
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// Step9:返回bean实例。
return exposedObject;
}
6.getObjectForBeanInstance() 源码分析
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// Step1:如果当前bean是以 “&”开头的并且是NullBean,则直接返回bean实例。
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
// Step2:当前bean实例是普通bean || 是以“&”开头的普通bean,则直接返回bean实例。
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
// Step3:从缓存中获取bean实例。
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
// Step4:从缓存中没有取到,则使用FactoryBean调用getObject()方法获取目标bean实例。
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
// Step5:返回目标bean实例。
return object;
}
该方法的主要作用其实一目了然,就是针对特殊的FactoryBean实例调用getObject()方法来获取目标bean实例。
7. 循环依赖解决方案剖析
假设现在有两个类,分别是 ClassA 和 ClassB,ClassA 有一个属性是 ClassB,ClassB 有一个属性是 ClassA。Spring 初始化的流程如下:
- 假设先初始化 ClassA,Spring 框架会先创建出 ClassA 的对应的 beanA 实例,但需要注意的是,此时仅仅是创建 beanA实例,并没有开始填充其属性
- 然后 Spring 将创建好的beanA 实例放入缓存中
- 获取 beanA 依赖的其他 bean 实例,即 ClassB 对应的 beanB 实例,但此时 beanB 实例还没被创建出来
- 创建 beanB 实例,同样也是创建出来一个空的 bean 实例,此时发现 beanB 实例依赖 beanA,于是存本地缓存中查询 beanA 实例并且获取到了。
- 通过第 4 步创建好了 beanB 实例,并将其也放入本地缓存后返回
- 经过第 4、5 步后,beanA 实例依赖的 beanB 实例被创建出来,然后在接着初始化 beanA 实例了。
8. 总结
本文讲解了关于singleton类型的 bean 实例的初始化流程(特意强调了是 singleton 类型的,后面我们再来研究下prototype类型的循环依赖问题),稍微比较复杂一点,需要 debug 代码多研究研究;下一篇接着讲讲 bean 实例初始化后,执行属性填充等一系列操作,敬请期待。
Spring源码阅读之初始化"非懒加载bean"实例-4
0. 导读
上一篇文章分析完了bean实例的创建,本文接着来讲讲bean实例的初始化结尾工作,主要介绍一下几个方面。
- populateBean():bean实例的属性填充工作。
- autowireByName()和autowireByType():两种bean实例的注入方式。
- applyPropertyValues():对bean实例填充相关的属性值。
- initializeBean():初始化bean实例。
1. 流程总览
2.populateBean() 流程分析
3.autowireByName() 流程分析
4.autowireByType() 流程分析
5.applyPropertyValues() 流程分析
6.initializeBean() 流程分析
7.invokeInitMethods() 流程分析
8. 总结
关于上一篇和这篇源码中,多次遇到了InstantiationAwareBeanPostProcessor和SmartInstantiationAwareBeanPostProcessor两个类,以防大家混淆,在这里特别说明一下。
- 类图继承关系如下:
- 关于两个接口提供的方法说明。
- InstantiationAwareBeanPostProcessor接口方法说明
- postProcessBeforeInstantiation():在bean实例创建前被调用,在这个时候可以使用动态代理创建bean实例等操作。
- postProcessAfterInstantiation():在bean实例创建后,属性设置前被调用,给出机会修改bean实例的状态。
- postProcessPropertyValues():主要作用是在设置属性前,用于修改属性值。
- SmartInstantiationAwareBeanPostProcessor接口方法说明
- predictBeanType():预测beanName对应的Class属性是否为指定的Class,如果是返回Class属性,反之返回null。
- determineCandidateConstructors():如果beanName对应的Class有多个构造器,则通过该方法来确定使用哪个构造器来创建bean实例,如果没有指定构造器,则使用默认的构造器来创建bean实例。
- getEarlyBeanReference():获取提前暴露的bean实例的引用,该方法主要用于解决scope类型为singleton的bean实例创建时面临的循环依赖问题。只有singleton的bean实例创建才会调用该方法。
到此,BeanDefinition定义解析和bean实例的初始化流程基本上就圆满完成了。下一篇我们开始一个新的概念,AOP思想在Spring框架中是怎么被运用的,敬请期待。(本文来自公众号:z小赵)
感谢大家支持,多多转发关注小编不迷路~~~~~~~