Spring源码学习(五):Bean的创建和获取

目录

1.获取Bean单例实例

2.完整创建Bean

2.1 Bean创建的前置处理

2.2 创建Bean:doCreateBean的createBeanInstance方法

2.2.1 通过Supplier实例化 —— obtainFromSupplier

2.2.2 通过factory-method实例化 —— instantiateUsingFactoryMethod

2.2.3 自动绑定构造函数 —— autowireConstructor

2.2.4 普通Bean的实例化 —— instantiateBean

2.3 Bean创建后的后处理:doCreateBean的剩余部分

2.3.1 调用PostProcessor

2.3.2 提前暴露

2.3.3 属性填充

2.2.4 Bean的初始化

2.3.5 继续处理提前暴露

2.3.6 Bean转化为DisposableBean

3.doGetBean的后续操作


当ApplicationContext完成refresh之后,容器就已经读取并解析了所有的Bean定义,安装了设定的扩展,并且对需要提前实例化的Bean创建了单例。这之后就可以获取XML中配置的Bean了,获取Bean的方法是容器的getBean()方法,实际调用了AbstractBeanFactory的doGetBean方法。

1.获取Bean单例实例

在容器扩展结束后,实际上已经对非懒加载、scope为“singleton”的Bean进行过实例化了,如果此时需要获取的Bean已经实例化,那么直接返回就可以,不需要重新实例化。

String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
    if (this.logger.isTraceEnabled()) {
        if (this.isSingletonCurrentlyInCreation(beanName)) {
            this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
        } else {
            this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
        }
    }
    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
}

transformedBeanName是将传入的名称通过在aliasMap中查找的方式,转换为BeanName。

getSingleton就是根据BeanName,尝试从存储Bean单例实例的Map中取出实例对象,假如单例对象不存在,或者正在创建,那么就尝试获取单例工厂,并产生单例对象:

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

earlySingletonObjects和singletonObjects的不同之处在于,前者包含了还处在创建过程中的单例对象,主要是用来防止循环依赖。只有当两个单例列表中都没有要找到Bean时,才会尝试创建一个。

紧接着,容器尝试从Bean实例中获取对象,之所以是获取对象而不是直接返回实例,从源码中就能看出原因:

    protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
            }
        }
        if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
            Object object = null;
            if (mbd == null) {
                object = this.getCachedObjectForFactoryBean(beanName);
            }
            if (object == null) {
                FactoryBean<?> factory = (FactoryBean)beanInstance;
                if (mbd == null && this.containsBeanDefinition(beanName)) {
                    mbd = this.getMergedLocalBeanDefinition(beanName);
                }
                boolean synthetic = mbd != null && mbd.isSynthetic();
                object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
            }
            return object;
        } else {
            return beanInstance;
        }
    }

原因就在于,Bean有两种,普通的Bean当然可以直接返回实例,但是对于FactoryBean,它是用来产生其他对象的,直接返回实例一般而言没有什么用,所以在这里需要进行判断。isFactoryDereference方法用来检测Bean名称是否以"&"开头,假如一个Bean不是FactoryBean却又以"&"开头,那么就是配置有问题,当然不能进行实例化。假如一个Bean是FactoryBean,且不以"&"开头,则说明用户想要它产生一个对象,则先尝试从缓存获取FactoryBean,否则用传入的Bean创建实例。由于传入的mbd是空,所以会触发getMergedLocalBeanDefinition方法,将本容器中名称为beanName的GenericBeanDefinition转换为RootBeanDefinition,假如要转换的是个子元素,则与父元素的相关属性进行合并。isSynthetic方法用于判断RootBeanDefinition是不是用户定义的。

getObjectForBeanInstance进行了一些判断,然后将核心逻辑交给了getObjectFromFactoryBean处理,它首先判断了传入的Bean是否是单例模式以及单例列表中是否有该Bean,如果答案全部都是true,则需要验证是不是已经创建过实例了,是则直接返回,否则尝试创建实例。实例创建成功后,还会根据是否需要后处理,执行相应方法:

synchronized(this.getSingletonMutex()) {
    Object object = this.factoryBeanObjectCache.get(beanName);
    if (object == null) {
        object = this.doGetObjectFromFactoryBean(factory, beanName);
        Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
        if (alreadyThere != null) {
            object = alreadyThere;
        } else {
            if (shouldPostProcess) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    return object;
                }
                this.beforeSingletonCreation(beanName);
                try {
                    object = this.postProcessObjectFromFactoryBean(object, beanName);
                } catch (Throwable var14) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var14);
                } finally {
                    this.afterSingletonCreation(beanName);
                }
           }
           if (this.containsSingleton(beanName)) {
               this.factoryBeanObjectCache.put(beanName, object);
           }
        }
    }
    return object;
}

假如判断有false,那么就简单了,由于没有限定Bean必须是单例,直接尝试让Factory产生对象即可。可以看到,这个方法又是进行了一些判断和后处理,核心逻辑又被委托给了doGetObjectFromFactoryBean,这次在代码中调用了factory.getObject()来产生对象。

2.完整创建Bean

2.1 Bean创建的前置处理

假如上一步获取单例实例时,单例列表中还没有需要的Bean的实例,说明待获取的Bean,要么其scope是prototype,要么它设置了lazy-init为true,即需要在使用时创建。代码首先判断了Bean是否正在创建,如果没有,则会检查当前BeanFactory是否包含需要创建的Bean定义,不包含则委托给父工厂创建,包含则自己创建。然后就会获取待创建Bean的RootBeanDefinition,并处理依赖关系:

RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null) {
    var11 = dependsOn;
    int var12 = dependsOn.length;
    for(int var13 = 0; var13 < var12; ++var13) {
        String dep = var11[var13];
        if (this.isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
         this.registerDependentBean(dep, beanName);
         try {
             this.getBean(dep);
         } catch (NoSuchBeanDefinitionException var24) {
             throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
         }
    }
}

getMergedLocalBeanDefinition上面有提到,作用是让子Bean元素继承父元素的属性;checkMergedBeanDefinition的作用是检查Bean是否是抽象的;dependsOn指的是由depends-on属性配置依赖的Bean,这些被依赖的Bean肯定是优先进行实例化的。处理依赖Bean时,首先检查了是否存在循环依赖,然后对Bean及其依赖注册依赖关系,最后尝试获取被依赖的Bean(如果被依赖的Bean还没初始化,会在这一步进行),假如该Bean不存在,则抛出异常。

接下来,开始根据Bean的不同scope采用不同的实例化方式,首先是单例Bean:

if (mbd.isSingleton()) {
    sharedInstance = this.getSingleton(beanName, () -> {
        try {
            return this.createBean(beanName, mbd, args);
        } catch (BeansException var5) {
            this.destroySingleton(beanName);
            throw var5;
        }    
    });
    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

核心方法就是createBean和getObjectForBeanInstance,后者已经见过了,主要看下前者,把日志、try-catch块都去掉,核心代码如下:

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        mbdToUse.prepareMethodOverrides();
        Object beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
        if (beanInstance != null) {
            return beanInstance;
        }
        return this.doCreateBean(beanName, mbdToUse, args);
    }

首先将beanName解析为Class对象,如有必要则赋给RootBeanDefinition对象,然后在prepareMethodOverrides方法中处理lookup-method和replace-method属性,在该方法中,检查了Bean类定义中,指定的覆盖方法的个数,并标记MethodOverride的overloaded属性,假如该属性为true,则实例化的时候会为这个Bean动态生成代理并进行增强处理。之后的resolveBeforeInstantiation就是在实例化前做些前置处理,实际调用了两个方法:applyBeanPostProcessorsBeforeInstantiation、applyBeanPostProcessorsAfterInitialization,前者是在AbstractBeanDefinition转换为BeanWrapper前最后一次可以修改BeanDefinition的机会,会调用PostProcessor对Bean进行处理:

    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeIns
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值