Spring源码系列——依赖注入(一)(AbstractBeanFactory-getBean)

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> Spring源码系列——依赖注入(一)(AbstractBeanFactory-getBean)

在Spring源码系列:BeanFactory的创建文章中我们谈到了BeanFactory这容器,这个里面提供了注入的实现接口。其具体的实现还需要从AbstractBeanFactory和DefaultListableBeanFactory中来看。今天就先撸一下AbstractBeanFactory这个类中的getBean这个方法。

1、getBean方法

getBean提供了四个重载方法,如下:


//通过name获取Bean
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
//通过name和类型获取Bean
@Override
public  T getBean(String name, Class requiredType) throws BeansException {
    return doGetBean(name, requiredType, null, false);
}
//通过name和对象参数获取Bean
@Override
public Object getBean(String name, Object... args) throws BeansException {
    return doGetBean(name, null, args, false);
}
//通过name、类型和参数获取Bean
public  T getBean(String name, Class requiredType, Object... args) throws BeansException {
    return doGetBean(name, requiredType, args, false);
}

从这四个重载方法的方法体中可以看出,他们都是通过doGetBean来实现的。所以doGetBean其实才是真正获取Bean的地方,也是触发依赖注入发生的地方。(这个方法比较长,分段来说)

2、doGetBean

先来看下方法的定义:


@SuppressWarnings("unchecked")
    protected  T doGetBean(
    final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
    throws BeansException {
  • name 要检索的bean的名称
  • requiredType 要检索的bean所需的类型
  • args 使用显式参数创建bean实例时使用的参数(仅在创建新实例时应用,而不是在检索现有实例时应用)
  • typeCheckOnly 是否为类型检查而获得实例,而不是实际使用
  • 
    //返回bean名称,剥离工厂引用前缀,并将别名解析为规范名称。
    final String beanName = transformedBeanName(name);
    //声明当前需要返回的bean对象
    Object bean;
    
    // 先从缓存中获取bean,处理已经被创建的单例模式的bean,
    //对于此类bean的请求不需要重复的创建(singleton)
    Object sharedInstance = getSingleton(beanName);
    

    如果当前获取到的sharedInstance不为null并且参数为空,则进行FactoryBean的相关处理,并获取FactoryBean的处理结果。

    
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            //返回指定的singleton bean是否正在创建(在整个工厂内)。
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("Returning eagerly cached instance of singleton bean '" 
                + beanName +"' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        //完成FactoryBean的相关处理,并用来获取FactoryBean的处理结果
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    

    如果当前获取到的sharedInstance为null,我们再来看下做了哪些处理(下面的都在一个大的else里面):

    
    else {
        //分解到下面
    }
    
    
    //在当前线程中,返回指定的prototype bean是否正在创建。
    if (isPrototypeCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
    

    下面这段的作用是对Ioc容器中的BeanDefinition是否存在进行检测,先是检测当前BeanFactory中是否能够获取到,如果取不到则继续到双亲容器中进行尝试获取,如果双亲还是取不到,则继续向上一级父容器中尝试获取。

    
    // 检查该工厂是否存在bean定义。
    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // 如果没有,则继续检查父类
        String nameToLookup = originalBeanName(name);
        if (args != null) {
            // 用明确的参数代表父项。
            return (T) parentBeanFactory.getBean(nameToLookup, args);
        }
        else {
            // 如果没有args - 委托给标准的getBean方法。
            return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
    }
    

    将指定的bean标记为已经创建(或即将创建);这里允许bean工厂优化其缓存以重复创建指定的bean。

    
    if (!typeCheckOnly) {
        markBeanAsCreated(beanName);
    }
    

    先根据beanName来获取BeanDefinition,然后获取当前bean的所有依赖bean,这里是通过递归调用getBean来完成,直到没有任何依赖的bean为止。

    
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    //检查给定的合并bean定义,可能抛出验证异常。
    checkMergedBeanDefinition(mbd, beanName, args);
    // 保证当前bean依赖的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);
            //递归处理依赖bean
            getBean(dep);
        }
    }
    

    下面这段就是创建一个bean实例;这里通过调用getSingleton方法来创建一个单例bean实例;从代码中可以看到,getSingleton的调用是通过getObject这个回调函数来间接调用createBean完成的。

    
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, new ObjectFactoryObject() {
        //回调函数getObject
            @Override
            public Object getObject() throws BeansException {
                try {
                    //创建bean
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    //发生异常则销毁
                    destroySingleton(beanName);
                    throw ex;
                }
            }
        });
        //获取给定bean实例的对象,无论是bean实例本身,还是FactoryBean创建的对象。
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    

    下面是创建prototype bean

    
    else if (mbd.isPrototype()) {
        Object prototypeInstance = null;
        try {
            beforePrototypeCreation(beanName);
            //创建prototype bean
            prototypeInstance = createBean(beanName, mbd, args);
        }
        finally {
            afterPrototypeCreation(beanName);
        }
        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    }
    

    最后是对创建的bean进行类型检查,没有问题就返回已经创建好的bean;此时这个bean是包含依赖关系的bean

    
    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
        try {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        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());
        }
    }
    //返回bean
    return (T) bean;
    

    getBean是依赖注入的起点,从上面的分析可以看出,bean的创建都是通过createBean来完成具体的创建的。createBean的具体实现是在AbstractAutowireCapableBeanFactory中的,这里createBean不仅仅负责创建bean,还需要完成对bean的初始化。

    原文始发于微信公众号(glmapper工作室):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> Spring源码系列——依赖注入(一)(AbstractBeanFactory-getBean)


     上一篇
    Spring源码系列-容器刷新——wac.refresh Spring源码系列-容器刷新——wac.refresh
    Spring对于程序员说来说都不陌生;作为一个强大的开源技术,帮助我们能够更好的进行项目的开发与维护。 上次在Spring的启动过程文章中对Spring的启动过程做了一个较为详细的说明和分析。那么在实际的过程中,Spring的启动实际上就
    2021-04-05
    下一篇 
    Spring源码系列——BeanDefinition载入(上) Spring源码系列——BeanDefinition载入(上)
    继上一篇BeanFactory的创建之后,其实就是BeanDefinition载入了。同样也是在AbstractRefreshableApplicationContext类的refreshBeanFactory方法中完成: //创建默认的
    2021-04-05