Spring IOC 源码之 getBean(二)

199 阅读5分钟

书接上文,我们讲完了doGetBean if 流程,下面我们继续康康有什么神奇的代码,废话不多说,show you the codes

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

1getParentBeanFactory 和循环依赖的处理

  1. 如果beanName是原型模式,且正在创建中,直接抛出异常
  2. 如果此时还没拿到bean,则加载父容器,如果父容器不为null 则通过父容器加载并返回bean
  3. 对bean进行标记,主要是将beanName 添加到alreadyCreated容器中
protected void markBeanAsCreated(String beanName) {
    // 没有创建
    if (!this.alreadyCreated.contains(beanName)) {
        // 加上全局锁
        synchronized (this.mergedBeanDefinitions) {
            // 再次检查一次:DCL 双检查模式
            if (!this.alreadyCreated.contains(beanName)) {
                // 从 mergedBeanDefinitions 中删除 beanName,
                // 并在下次访问时重新创建它。
                clearMergedBeanDefinition(beanName);
                // 添加到已创建bean 集合中
                this.alreadyCreated.add(beanName);
            }
        }
    }
}

  1. 通过getMergedLocalBeanDefinition获取RootBeanDefinition实例,并进行检查
  2. 针对单例模式进行依赖的处理
  • 首先使用String[] dependsOn = mbd.getDependsOn() 获取当前bean的所有依赖属性
  • 通过isDependent 方法判断是否有循环依赖,这里有递归调用,如果没有循环依赖则调用registerDependentBean 进行注册,主要是更新表格里的2个Map
  • getBean(dep)是为了加载当前bean依赖的bean
Map作用
dependentBeanMap依赖当前bean的集合
dependenciesForBeanMap当前Bean所依赖的Bean的集合 存储格式 beanName -> 该bean依赖的bean集合
protected boolean isDependent(String beanName, String dependentBeanName) {
    synchronized (this.dependentBeanMap) {
        return isDependent(beanName, dependentBeanName, null);
    }
}

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {

    // alreadySeen 已经检测到的依赖 bean
    if (alreadySeen != null && alreadySeen.contains(beanName)) {
        return false;
    }
    // 获取原始 beanName 之前讲过我们就不多少了
    String canonicalName = canonicalName(beanName);
    // 获取当前 beanName 的依赖集合
    Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
    // 不存在依赖,返回false
    if (dependentBeans == null) {
        return false;
    }
    // 存在,则证明存在已经注册的依赖
    if (dependentBeans.contains(dependentBeanName)) {
        return true;
    }
    // 递归检测依赖
    for (String transitiveDependency : dependentBeans) {
        if (alreadySeen == null) {
            alreadySeen = new HashSet<>();
        }
        alreadySeen.add(beanName);
        if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
        }
    }
    return false;
}
    
    
public void registerDependentBean(String beanName, String dependentBeanName) {
    String canonicalName = canonicalName(beanName);

    synchronized (this.dependentBeanMap) {
        Set<String> dependentBeans =
                this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }

    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean =
                this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        dependenciesForBean.add(canonicalName);
    }
}

2 各个作用域bean的获取

2.1 单例bean的获取

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

书接第一篇Spring IOC 源码之 getBean(一) ,如果缓存中没有我们需要的bean,我们只能从头开始加载bean,那么getSingleton(String beanName, ObjectFactory<?> singletonFactory) 就要粉墨登场啦

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");

    // 全局加锁
    synchronized (this.singletonObjects) {
        // 1 因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 2 前置处理 省略部分代码
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            // 省略代码
            try {
                // 3 这个过程其实是调用 createBean() 方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            } finally {
                // 4 后置处理
                afterSingletonCreation(beanName);
            }
            // 5 加入缓存中
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        // 直接返回
        return singletonObject;
    }
}

1.this.singletonObjects.get(beanName) 通过缓存获取bean 2. 如果为空, 则通过beforeSingletonCreation(beanName) 进行前置处理,同时定义一个属性newSingleton 为false

protected void beforeSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

  1. 通过singletonFactory.getObject() 获取bean,同时标记为newSingletion
  2. 进行后置处理
  3. 加入缓存
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

2.2 原型模式bean的获取

else if (mbd.isPrototype()) {
    Object prototypeInstance = null;
    try {
        beforePrototypeCreation(beanName);
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
  1. 调用 beforeSingletonCreation() 记录加载原型模式 bean 之前的加载状态,即前置处理。
  2. 调用 createBean() 创建一个 bean 实例对象。
  3. 调用 afterSingletonCreation() 进行加载原型模式 bean 后的后置处理。
  4. 调用 getObjectForBeanInstance() 从 bean 实例中获取对象。

2.3 其他作用域

其他作用域的偷个懒,暂时不做分析,有兴趣的小伙伴自己自行了解