今天看啥  ›  专栏  ›  不秃头的王小闹

Spring IOC 源码之 getBean(一)

不秃头的王小闹  · 掘金  ·  · 2021-03-20 16:46
阅读 12

Spring IOC 源码之 getBean(一)

1 SpringIoc大体上可以分为2个阶段

  1. 加载资源。这里的资源主要是指配置信息(XML文件,@Bean注解这些),主要是通过 ResourceResourceLoader 2大工具来进行加载和解析。其中Resource 主要负责资源定位,ResourceLoader主要负责资源的加载,通过这2步后,配置信息被组装成BeanDefinition,并保存在 BeanDefinitionRegistry 中。
  2. 加载bean。经过第一步,Spring已经将配置信息转换成Bean放到了 BeanDefinitionRegistrygetBean()方法会触发bean的加载。该系列文章主要讲解第二步的详细过程,第一步暂时忽略,介意的胖友们可以自行百度

2 开始加载过程

2.1 getBean()

源码如下,代码很长,胖友们不要害怕,我们一步一步分析哈

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 {

    //1 获取 beanName,主要是处理alias 和factorybean的 "&"
    final String beanName = transformedBeanName(name);
    Object bean;

    //2 从缓存中或者实例工厂中获取 bean
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        //3 删除无用的日志代码 通过 getObjectForBeanInstance 获取bean实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {

        // 4 检查原型模式
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        //5 加载父类容器中,如果父容器不为空,且当前容器中没有改bean,则通过父容器加载
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        // 6 记录bean已经被创建过
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            // 7 beanName 相应的 GenericBeanDefinition,并且转换为  RootBeanDefinition,并对其进行检测
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // 8 处理所依赖的 bean,这里有如何判断循环依赖的方法
            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 {
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 9 单例模式的bean 实例化
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // 10 如果创建失败执行销毁过程(单例模式下为了解决循环依赖,可能已经提前暴露了该bean)
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            // 11  原型模式
            else if (mbd.isPrototype()) {
             
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                // 12 其他的scope 
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                    "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // 13 检查需要的类型是否符合 bean 的实际类型
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}
复制代码

2.1.1 transformedBeanName(name)

先附上源码

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

// 去除 FactoryBean 的修饰符
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    String beanName = name;
    while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
    }
    return beanName;
}

// 转换 aliasName
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;
}

复制代码
  1. 去除FactoryBean & 开头
  2. 转换别名,Spring是依赖HashMap 来管理别名,其格式是 aliasName -> beanName, 也会存在多重别名,所以这里有循环处理,直到 resolvedName = null ,则说明已经拿到最终的 beanName

2.1.2 getSingleton(beanName)

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 1 从单例缓存中加载 bean
    Object singletonObject = this.singletonObjects.get(beanName);

    // 2 缓存中的 bean 为空 && 当前 bean 正在创建
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 加同步锁
        synchronized (this.singletonObjects) {
            // 从 earlySingletonObjects 获取
            singletonObject = this.earlySingletonObjects.get(beanName);
            // earlySingletonObjects 中没有,且允许提前创建
            if (singletonObject == null && allowEarlyReference) {
                // 从 singletonFactories 中获取对应的 ObjectFactory
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                // ObjectFactory 不为空,则创建 bean
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

 public boolean isSingletonCurrentlyInCreation(String beanName) {
    return this.singletonsCurrentlyInCreation.contains(beanName);
}
复制代码
  1. 首先从singletonObjects 获取bean
  2. 如果singletonObject == null 且 该bean正在创建过程中
  3. 加同步锁,然后从earlySingletonObjects 中获取,
  4. 如果singletonObject 还是null,并且允许提前加载,则从singletonFactories 中获取ObjectFactory<?> singletonFactory,然后通过 工厂方法的singletonFactory.getObject()获取singletonObject,同时加入到earlySingletonObjects, 从singletonFactories移除
  5. singletonsCurrentlyInCreation 主要用于判断bean是否在创建过程中,看到这里,我们可以大胆的猜测下,所有的bean在创建初期都会加入到该Map中,那么加入的时机是?答案后面的文章会慢慢揭晓哈

这里有三个Map,下面我们逐一分析下

名称功能
singletonObjects存储关系为 beanName-> bean instance,存放单例的bean
earlySingletonObjects存储关系为 beanName->bean instance,它和 singletonObjects的区别是singletonObjects是存放的完整的bean instance,earlySingletonObjects存放的是早期的bean,不一定是完整的(因为spring允许提前暴露,这也是解决循环依赖的关键哈)
singletonFactories关系为 beanName-> BeanFactory,存放单例的bean 的 factory

2.1.3 getObjectForBeanInstance

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

    // 1 工厂类引用下的一些判断
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        // 如果是 NullBean,则直接返回
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        // 2 如果 beanInstance 不是 FactoryBean 类型,则抛出异常,double check? 因为前面已经做了一次判断,才能走进这个if啊
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    }

    // 3 走到这里我们得到了一个bean实例 或者一个FactoryBean实例  如果是 FactoryBean,我我们则创建该 bean
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    //4 加载 FactoryBean
    Object object = null;
    // 若 BeanDefinition 为 null,则从缓存中加载
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    // 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean
    if (object == null) {
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        //
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        // 是否是用户定义的而不是应用程序本身定义的
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 5 核心处理类
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

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

复制代码
  1. 针对工厂Bean(以&) 开头,如果为NullBean,直接返回,
  2. 走进1的 分之后,如果不是工厂Bean 返回异常
  3. 走到这一步,我们获取到了一个bean实例,要么是正常Bean 要么就是 FactoryBean

4.BeanDefinition is null 则从factoryBeanObjectCache 中获取 5. 核心方法还是getObjectFromFactoryBean

2.1.4 getObjectFromFactoryBean 从FactoryBean 工厂获取Bean

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 1 为单例模式且缓存中存在
    if (factory.isSingleton() && containsSingleton(beanName)) {

        synchronized (getSingletonMutex()) {
            // 2 从缓存中获取指定的 factoryBean
            Object object = this.factoryBeanObjectCache.get(beanName);

            if (object == null) {
                // 3 为空,则从 FactoryBean 中获取对象
                object = doGetObjectFromFactoryBean(factory, beanName);

                // 从 factoryBeanObjectCache 缓存中获取
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                // 这里是做咩的啊,
                if (alreadyThere != null) {
                    object = alreadyThere;
                }
                else {
                    // 4 需要后续处理
                    if (shouldPostProcess) {
                        // 若该 bean 处于创建中返回bean
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            return object;
                        }
                        // 5 前置处理
                        beforeSingletonCreation(beanName);
                        try {
                            // 对从 FactoryBean 获取的对象进行后处理
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            // 6 后置处理
                            afterSingletonCreation(beanName);
                        }
                    }
                    // 7 加入缓存
                    if (containsSingleton(beanName)) {
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
    else {
        // 8 非单例 模式
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        if (shouldPostProcess) {
            try {
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        return object;
    }
}

复制代码
  1. 判断是否是单例模式且 单例缓存containsSingleton 存在该beanName
  2. 通过factoryBeanObjectCache 获取指定的 factoryBean
  3. factoryBean 为null 则通过doGetObjectFromFactoryBean 通过 FactoryBean.getObject() 获取factoryBean
  4. 判断是否需要后续处理
  • 通过 beforeSingletonCreation 创建前处理,代码如下。敲黑板,这里就有singletonsCurrentlyInCreation 的add操作哦
protected void beforeSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}
复制代码

-postProcessObjectFromFactoryBean() 对从 FactoryBean 处获取的 bean 实例对象进行后置处理,其默认实现是直接返回 object 对象。AbstractAutowireCapableBeanFactory 对其进行了重写,我们先了解下代码,具体后续再补充

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

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

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
复制代码
  • afterSingletonCreation 创建后处理
protected void afterSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
}
复制代码
  1. 加入到 FactoryBeans



原文地址:访问原文地址
快照地址: 访问文章快照