Spring Bean实例化过程详解

且挨过三冬四夏,暂受些此痛苦。雪尽后再看梅花。

这篇讲解SpringBean实例化过程的关键代码,代码目录可以查找上篇。

首先是getBean->doGetBean

final String beanName = this.transformedBeanName(name);

这里传入的名称可能是别名,做别名解析

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject != NULL_OBJECT ? singletonObject : null;
    }

走到getSingleton()去缓存池中获取对象,如果singletonObjects和earlySingletonObjects中都没有且singletonFactories里有,会调用getObject()方法获取早期对象,并放入earlySingletonObjects且从singletonFactories中移除包装对象。

bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);

如果获取到了对象,调用getObjectForBeanInstance处理这里可能是工厂Bean的情况,然后直接返回bean并结束

BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
    String nameToLookup = this.originalBeanName(name);
    if (args != null) {
        return parentBeanFactory.getBean(nameToLookup, args);
    }
    return parentBeanFactory.getBean(nameToLookup, requiredType);
}

如果没有获取到对象,则尝试获取父工厂,如果父工厂不为空且当前容易不包含他的bean定义,那么走父工厂的创建流程(回到开始)

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

合并Bean定义,如果存在父Bean是一个抽象Bean

checkMergedBeanDefinition(mbd, beanName, args);

校验当前bean定义不能为抽象

registerDependentBean(dep, beanName);

解析depend-on的bean,如果依赖其他bean需要先创建依赖的bean,这个时候如果A dependon B,B dependon A,会报错

然后根据scope类型来创建Bean,这里只解析单例bean,因为其他类型的都不由spring管理其生命周期

sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
    public Object getObject() throws BeansException {
        try {
            return AbstractBeanFactory.this.createBean(beanName, mbd, args);
        } catch (BeansException var2) {
            AbstractBeanFactory.this.destroySingleton(beanName);
            throw var2;
        }
    }
});
protected void beforeSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

放入singletonsCurrentlyInCreation中表示该对象正在创建

singletonObject = singletonFactory.getObject();

调用getObject()方法即createBean()方法

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

这里是aop的内容,会把切面信息解析并缓存,之后写aop的内容时详解这部分

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

instanceWrapper = createBeanInstance(beanName, mbd, args);

真正创建bean的流程

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized(this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

把刚刚创建好的对象 属性还没有赋值的对象通过ObjectFactory的形式加入到缓存中(重要!重要!重要!文章后面会讲下这里怎么解决了循环依赖)

populateBean(beanName, mbd, instanceWrapper);

属性赋值

applyPropertyValues(beanName, mbd, bw, pvs);

获取完所有需要注入的属性后,进行应用

Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

转换属性

if (value instanceof RuntimeBeanReference) {
    RuntimeBeanReference ref = (RuntimeBeanReference) value;
    return resolveReference(argName, ref);
}

如果是运行时Bean,解决引用

bean = this.beanFactory.getBean(refName);

从容器中获取bean(回到开头)

exposedObject = initializeBean(beanName, exposedObject, mbd);

赋值完成后进行对象初始化操作

// 进行Aware接口的回调
invokeAwareMethods(beanName, bean);
// 调用后置处理器的before方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 调用初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
// 调用后置处理器的after方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

createBean执行完毕后回到getSingleton方法

afterSingletonCreation(beanName);

把当前的bean从singletonsCurrentlyInCreation中移除掉

addSingleton(beanName, singletonObject);

加入到一级缓存中,并清除二三级缓存中该对象的信息

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

处理工厂bean然后返回对象,整个流程执行结束


所以如果A引用B,B引用A,在创建A的过程中,
在addSingletonFactory将早期对象的包装对象放到缓存中,
在populateBean给属性赋值时解析到了B的引用,走创建B的流程
创建B时进行populateBean时可以获取到A的早期对象,继续进行创建流程
最后将创建好的对象保存在一级缓存中并返回
A获取到B对象继续属性赋值,创建好后保存在一级缓存中并返回

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值