SpringIoc源码(十五)- BeanFactory(四)- getBean(doGetBean上 - 缓存中获取)

目录

下面为非第一次getBean(已经初始化过一次),获取的最短路径

1、获取真实的BeanName(传入的可能是别名等)

     1)、判断是否为获取FactoryBean

    2)、 判断是否为别名

2、从缓存中获取实例(如果已经调用过getBean)

3、判断返回真正获取的对象

1、如果源名称以&开头,则判断是否为NullBean,判断是否不存在(直接抛异常),返回工厂本身

2、获取正常的Bean(非FactoryBean类型),则直接返回。

3、不是获取FactoryBean本身,但是获取的是FactoryBean类型的Bean

3-1)、从缓存中获取(非第一次)

3-2)、获取实例(第一次获取)


    之所以先写了ApplicationContext的refresh方法再写继续写BeanFactory的getBean核心方法,是因为觉得项目中根本不会直接使用BeanFactory肯定还是会使用ApplicationContext。并且每个Bean的生命周期会在getBean中完成,其中就会回调所有的BeanPostProcessorpostProcessBeforeInitializationpostProcessAfterInitialization方法。

    先梳理一下getBean的整个过程(只分析单利Bean)

    1、首先会从缓存中获取;否则(第一次)需要根据之前注入的BeanDefinition进行创建。

    2、创建之前需要先处理ovverride和前置准备;在创建时会有依赖注入的情况(需要解决循环依赖的问题),则再分析真正的创建

    3、创建过程:创建Bean实例;记录创建Bean的工厂;属性注入;初始化Bean(Bean的生命周期在这里完成,包括注册DisposableBean)

 

下面为非第一次getBean(已经初始化过一次),获取的最短路径

    开始:

@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    final String beanName = transformedBeanName(name);

    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    // 省略
}

1、获取真实的BeanName(传入的可能是别名等)

    调用getBean方法时候,传入的字符串可能是别名,或者是FactoryBean类型则可能传入&开头的,以获取FactoryBean本身。所以需要考虑各种情况,拿到真是的bean名称。

protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

     1)、判断是否为获取FactoryBean

public static String transformedBeanName(String name) {
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

    判断名称是否以&开头,不是则直接返回当前字符串;是则是获取FactoryBean本身,则需要截取字符串,缓存获取FactoryBean的名称。缓存到BeanFactoryUtils

Map<String, String> transformedBeanNameCache

    2)、 判断是否为别名

public String canonicalName(String name) {
    String canonicalName = name;
    String resolvedName;
    do {
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

  当前字符串要不是Bean名称本身,要不是就是别名。那么直接在别名中获取一下,有则返回别名,否则返回Bean名称本身。

 

2、从缓存中获取实例(如果已经调用过getBean)

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

    如果第一次调用getBean初始化完成后,则会将实例化的Bean放入DefaultSingletonBeanRegistrysingletonObjects容器中;为了解决单利循环依赖的问题,则在依赖注入时,会提前将未完成的Bean提前放入earlySingletonObjects容器中。创建Bean的工厂与Bean名称的关系存储在singletonFactories容器中。

  1. 先直接先看是否初始化完成,如果没有拿到,则判断是否正在创建中。
  2. 如果是则从earlySingletonObjects中进行获取。并且当前allowEarlyReference参数为true,则如果正在依赖注入创建中,直接从工厂中获取
  3. 如果工厂已经存在,则直接getBean调用工厂的getBean方法,并且提前暴露放到earlySingletonObjects中。

3、判断返回真正获取的对象

if (sharedInstance != null && args == null) {
    // 省略日志
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

    上面获取到的可能就是需要返回的Bean,但是当前可能需要获取的是FactoryBean本身(是否或者FactoryBean已经缓存到BeanFactoryUtilstransformedBeanNameCache中)。获取时传入了上面获取的实例,源名称,Bean名称,RootBeanDefinition为null。

@Override
protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    String currentlyCreatedBean = this.currentlyCreatedBean.get();
    if (currentlyCreatedBean != null) {
        registerDependentBean(beanName, currentlyCreatedBean);
    }

    return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}

     判断当前是否正在有依赖注入的Bean没有初始化完成(非第一次调用则肯定已经初始化完成了),在继续调用父类AbstractBeanFactory的方法。

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.
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        return beanInstance;
    }

    // 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.
    if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd != null) {
        mbd.isFactoryBean = true;
    }
    else {
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // Return bean instance from factory.
        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);
    }
    return object;
}

1、如果源名称以&开头,则判断是否为NullBean,判断是否不存在(直接抛异常),返回工厂本身

2、获取正常的Bean(非FactoryBean类型),则直接返回。

3、不是获取FactoryBean本身,但是获取的是FactoryBean类型的Bean

 

3-1)、从缓存中获取(非第一次)

getCachedObjectForFactoryBean(beanName);

    则在AbstractBeanFactory的父类FactoryBeanRegistrySupport,的factoryBeanObjectCache容器中获取

@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
    return this.factoryBeanObjectCache.get(beanName);
}

3-2)、获取实例(第一次获取)

    那么上面获取到的beanInstance为FactoryBean,先或者合并的BeanDefinition,再判断是否为synthetic(合成的)。

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 判断为单利
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            // 从缓存中判断
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // 直接用FactoryBean中调用getObject方法获取,或者判断是否正在创建中
                object = doGetObjectFromFactoryBean(factory, beanName);
                // Only post-process and store if not put there already during getObject() call above
                // (e.g. because of circular reference processing triggered by custom getBean calls)
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                }
                else {
                    if (shouldPostProcess) {
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            // Temporarily return non-post-processed object, not storing it yet..
                            return object;
                        }
                        beforeSingletonCreation(beanName);
                        try {
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            afterSingletonCreation(beanName);
                        }
                    }
                    if (containsSingleton(beanName)) {
                        // 放入缓存中,第二次就从缓存中获取
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
    // 省略非单利
}

    先用synchronized锁住singletonObjects,又从缓存中获取一遍。

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
        throws BeanCreationException {

    Object object;
    try {
        if (System.getSecurityManager() != null) {
            AccessControlContext acc = getAccessControlContext();
            try {
                object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            object = factory.getObject();
        }
    }
    catch (FactoryBeanNotInitializedException ex) {
        throw new BeanCurrentlyInCreationException(beanName, ex.toString());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
    }

    // Do not accept a null value for a FactoryBean that's not fully
    // initialized yet: Many FactoryBeans just return null then.
    if (object == null) {
        if (isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(
                    beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
        object = new NullBean();
    }
    return object;
}

     否则直接从FactoryBean中获取,但是可能或者不到,则判断是否正在创建中,则后面从创建中获取。主要的方法就是FactoryBean#getObject方法。第一次获取,则也会执行FactoryBean类型的Bean的生命周期的 回调BeanPostProcess的方法。比如之前修改jpa的JpaRepository子类(通过JpaRepositoryFactoryBean#getObject创建)就有该回调。如下:

@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
    return applyBeanPostProcessorsAfterInitialization(object, beanName);
}

    但是只回调了所有BeanPostProcessorpostProcessAfterInitialization方法:

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

    最后将FactoryBean通过getObject方法,获取到的对象放入factoryBeanObjectCache缓存,第二次就可以从该容器中获取了

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值