Spring 的 getBean 方法源码解析

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

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

原文链接:blog.ouyangsihai.cn >> Spring 的 getBean 方法源码解析

文本将从以下几个方面介绍

  • FactoryBean 接口
  • BeanFactory 接口
  • BeanFactory 接口 和 FactoryBean 接口的区别
  • getBean 方法的源码解析
  • Spring 循环依赖的解决方式
  • 相关文章

    前言

    在文章  和  了解了 bean 的注册和创建过程,当通过 getBean 方法来获取对应 bean 的时候,会是如何的呢?

    下面就来看看 getBean 方法的内部实现。在进入 getBean 方法内部之前,先来看看 FactoryBean 这个接口,因为在 getBean 方法内部会对该接口的实现类进行另外的处理。

    FactoryBean

    这个接口和 BeanFactory 接口非常的像,但是作用却截然不同,先来看看 javadoc 文档的定义,大致意思就是:如果某个 bean 实现了这个接口,通过 getBean 方法来获取 bean 的时候,并不是返回自己的实例,而是返回其 getObject() 方法的返回值;此外 FactoryBeans 可以支持 singletons 和  prototypes 模式。它的源码如下,只有 三个 方法:

    
    public interface FactoryBeanT {
        // 返回 bean 的实例,即调用 getBean 方法获取到的实例就是该方法的返回值 
        T getObject() throws Exception;
    
        // 返回 bean 的类型
        Class? getObjectType();
    
        // 该 bean 是否是单例模式
        boolean isSingleton();
    }
    

    那么这个 FactoryBean 接口有什么用呢?通过  知道, bean 的实例化就是使用 反射 CGLIB来实现的,但是在某些情况下,实例化 bean 过程比较复杂,如果按照传统的方式,则需要在配置文件 bean 中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。所以,用户可以通过实现该接口定制实例化 bean 的逻辑。

    栗子

    先来看一个栗子,现在有个 User 对象,传统的方式,在配置文件中配置如下:

    
    public class User {
    
        private String name;
        private int age;
        private int sex;
        private double money;
        private String job;
    
        // setter / getter / toString
    }
    bean id="user" class="main.tsmyk.pojo.User"
        property name="name" value="zhangsan"/
        property name="age" value="20"/
        property name="job" value="java"/
        property name="money" value="10000"/
        property name="sex" value="1"/
    /bean
    

    测试:

    
    ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
    User user = (User) context.getBean("user");
    System.out.println(user);
    结果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}
    

    从打印的结果可以看到 User 对象的属性都被附上了值

    但是,如果 User 对象的属性很多,不想写很多的 property 标签,则可以通过 ** FactoryBean**接口来实现,在该接口内部,按照一定的规则来解析 User 对象的属性并赋值。如下所示:

    
    public class UserFactoryBean implements FactoryBeanUser {
    
        private String user;
    
        @Override
        public User getObject() throws Exception {
            User user = new User();
            String[] userInfos = this.user.split(";");
            user.setName(userInfos[0]);
            user.setAge(Integer.parseInt(userInfos[1]));
            user.setJob(userInfos[2]);
            user.setMoney(Double.parseDouble(userInfos[3]));
            user.setSex(Integer.parseInt(userInfos[4]));
            return user;
        }
    
        @Override
        public ClassUser getObjectType() {
            return User.class;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    
        public String getUser() {
            return user;
        }
        public void setUser(String user) {
            this.user = user;
        }
    }
    

    在该类的 getObject 方法内部对 User 对象的属性进行解析并赋值,通过 getBean方法获取 bean 的时候,得到的就是 getObject 方法返回的 User 对象,配置如下:

    
    bean id="userFactory" class="main.tsmyk.beans.UserFactoryBean"
        property name="user" value="zhangsan;20;java;10000;1"/
    /bean
    

    测试:

    
    ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
    User user1 = (User) context.getBean("userFactory");
    System.out.println(user1);
    
    结果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}
    

    可以看到和上面传统的方式是一样的。也验证了 getBean方法获取到的是 getObject 方法的返回值,而不是 FactoryBean 实例本身;但是,如果就想获取到 FactoryBean 的实例本身,也是可以的,在 bean 的名字前加 & 符号就可以了,即 getBean("&userFactory")

    测试:

    
    ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
    UserFactoryBean userBean = (UserFactoryBean) context.getBean("&userFactory");
    System.out.println(userBean.getUser());
    
    结果:zhangsan;20;java;10000;1
    

    敲黑板:所以说,通过 getBean(String beanName) 方法来获取实例的时候, beanName 有可能是以 & 开头的,如果 beanName & 开头,就表示处理的是 FactoryBean 接口

    Spring 自身也提供了 FactoryBean  接口的很多实现,如 JndiObjectFactoryBean 类:

    
    public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryBeanObject, BeanFactoryAware, BeanClassLoaderAware {
        private Object jndiObject;
        // 其他复杂的计算,为 jndiObject 赋值
        @Override
        public Object getObject() {
            return this.jndiObject;
        }
    }
    

    我们熟知的第三方 ORM 框架 Mybatis 也提供了该接口的实现 SqlSessionFactoryBean

    
    bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
        // 其他配置
    /bean
    public class SqlSessionFactoryBean implements FactoryBeanSqlSessionFactory, InitializingBean, ApplicationListenerApplicationEvent {
      private SqlSessionFactory sqlSessionFactory;
      @Override
      public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
          afterPropertiesSet();
        }
    
        return this.sqlSessionFactory;
      }
      // 其他方法
    }
    

    所以通过 getBean 方法获取的时候,得到的是 SqlSessionFactory 而不是 SqlSessionFactoryBean

    BeanFactory

    现在来看看和 FactoryBean 很相似的一个接口 BeanFactory ,** BeanFactory** 它是 Spring  IOC 容器的核心接口,它定义了容器的主要功能,如创建 bean,获取 bean 等,它是用来管理 bean 的,即它是用来实例化、定位、配置应用程序中的对象及建立这些对象间的依赖关系的。它的源码如下:

    
    public interface BeanFactory {
    
        String FACTORY_BEAN_PREFIX = "&";
        Object getBean(String name) throws BeansException;
         T getBean(String name, Class requiredType) throws BeansException;
        Object getBean(String name, Object... args) throws BeansException;
         T getBean(Class requiredType) throws BeansException;
         T getBean(Class requiredType, Object... args) throws BeansException;
        boolean containsBean(String name);
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
        boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
        boolean isTypeMatch(String name, ResolvableType typeToMatch);
        boolean isTypeMatch(String name, Class? typeToMatch) throws NoSuchBeanDefinitionException;
        Class? getType(String name) throws NoSuchBeanDefinitionException;
        String[] getAliases(String name);
    }
    

    可以看到定义了容器的基本功能,注意它有一个属性 FACTORY_BEAN_PREFIX = "&" 就是用来表示 FactoryBean 接口的 beanName 的前缀。

    总结

    到这里,通过源码就可以看到,虽然 FactoryBean BeanFactory 很像,但它们的作用完全不同,
    FactoryBean 可以看做一个工厂,用它来创建一些复杂的 bean
    BeanFactory 定义了 Spring 容器基本的功能,交由子类去实现,用于管理 bean

    getBean 方法

    User user = (User) beanFactory.getBean(“user”);

    
        @Override
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
    
        @Override
        public  T getBean(String name, Class requiredType) throws BeansException {
            return doGetBean(name, requiredType, null, false);
        }
    
        @Override
        public Object getBean(String name, Object... args) throws BeansException {
            return doGetBean(name, null, args, false);
        }
    

    接下来看下 doGetBean 方法,该方法有点复杂:

    
    protected  T doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly){
        // 提取对应的 beanName,处理别名和FactoryBean接口的实现类,即 beanName 以 & 开头
        final String beanName = transformedBeanName(name);
        Object bean;
        // 尝试从缓存中或者ObjectFactory中获取
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("......");
            }
            // 这里主要处理 FactoryBean,有时候并不是返回实例本身,而是返回指定方法返回的实例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        // 缓存中不存在该bean的实例
        else {
            // 这里bean的作用域是原型模式,且存在循环依赖,出现循环依赖,则抛出异常
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 如果当前的的beanDefinitionMap即配置文件不包含该bean,则从parentBeanFactory 中查找
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // 这个 args 是 getBean(beanName, args...) 方法传入的
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }
            // 如果不仅仅是做类型检查,则是创建bean,则进行标记,标记该bean以创建
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
            // 将配置文件中GenericBeanDefinition转换为RootBeanDefinition,如果beanName是子bean的话,会合并父类的属性
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);
    
            // 处理依赖,如果存在依赖,则递归实例化依赖的bean
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                            throw new BeanCreationException("........");
                    }
                    registerDependentBean(dep, beanName);
                    getBean(dep);
                }
            }
            //实例化 bean
            if (mbd.isSingleton()) {
                // 实例化单例的bean
                sharedInstance = getSingleton(beanName, new ObjectFactoryObject() {
                    @Override
                    public Object getObject() throws BeansException {                   
                        return createBean(beanName, mbd, args);
                    });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            else if (mbd.isPrototype()) {
                // 实例化原型的bean
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
            else {
                // 指定的 score 上实例化bean
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                Object scopedInstance = scope.get(beanName, new ObjectFactoryObject() {
                    @Override
                    public Object getObject() throws BeansException {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                        });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                }
            }
        }
        // 处理参数类型的转换
        if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        return (T) bean;
    }
    

    从 上述的代码可以看到, doGetBean 方法流程是很清晰的,每一步都使用对应的方法进行处理,它的流程主要如下:

  • 处理 `beanName`,为什么要处理 `beanName`呢,因为 bean 是可以有别名的,且,在上面介绍 `FactoryBean` 接口的时候,获取该 bean 的时,需要加上 `&` 前缀,所以这里要去掉`&`
  • 尝试从缓存中加载该 bean,因为单例的 bean 只会加载一次,如果缓存中不存在该 bean,则会尝试从 `singletonFactories` 中加载,这个 `singletonFactories` 是什么呢? 在  知道, bean 在创建的时候可能会存在依赖注入的情况,而在创建依赖 bean 的时候,为了 避免循环依赖,那么在创建该 bean 的时候,不等到 bean 创建完成就会把创建该 bean 的 `ObjectFactory`放到 `singletonFactories`  缓存中,一旦下一个 bean 创建的时候,需要依赖上一个 bean 则直接从 `singletonFactories`  缓存中获取该 `ObjectFactory` 来进行创建,

    比如 A 依赖 B,A -- B,现在创建 A 的实例 beanA,创建过程中,就把创建 A 的`ObjectFactory` 放到 `singletonFactories`   缓存中,现在发现 A 依赖于 B,则现在要去创建 B 的实例 beanB,当创建完 beanB 后才会继续创建 beanA; 如果现在发现 B 也依赖于 A,B -- A,那么在创建 beanB 的时候,也会先去创建 beanA,因为之前创建 A 的实例 beanA 的时候,已经把 A 的 `ObjectFactory` 放入到 缓存中了,现在直接去缓存中取出该 `ObjectFactory` 即可,试想一下,如果没有事先把 A 的 `ObjectFactory` 放到缓存中,那么在创建 B 的时候,先去创建 A ,创建 A  的时候发现依赖 B ,则又会去 创建 B,这样就会造成循环依赖,就会实例化失败。

  • 尝试从缓存中加载该 bean,因为单例的 bean 只会加载一次,如果缓存中不存在该 bean,则会尝试从 singletonFactories 中加载,这个 singletonFactories 是什么呢? 在  知道, bean 在创建的时候可能会存在依赖注入的情况,而在创建依赖 bean 的时候,为了 避免循环依赖,那么在创建该 bean 的时候,不等到 bean 创建完成就会把创建该 bean 的 ObjectFactory放到 singletonFactories  缓存中,一旦下一个 bean 创建的时候,需要依赖上一个 bean 则直接从 singletonFactories  缓存中获取该 ObjectFactory 来进行创建,

    所以 Spring 是通过这种方法是解决 bean 之间循环依赖的,但是仅仅是处理单例的循环依赖,原型或其他的则会抛出异常

  • 创建 bean 3.1 从父类查找 bean 3.2 将 `GenericBeanDefinition` 转换为 `RootBeanDefinition`,因为从配置文件加载 bean 的时候,是以 `GenericBeanDefinition` 方式保存的 3.3 处理依赖 3.4 创建 单例的 bean 3.5 创建 原型的 bean 3.6 创建其他 score 作用于的 bean 3.7 参数类型的转换

  • 处理 FactoryBean 接口的 bean
  • 处理 FactoryBean 接口的 bean

    流程是不是很清晰,再通过流程图来看更清晰:

    Spring 的 getBean 方法源码解析

    下面看看每个部分。

    1. 提取 beanName

    当通过 getBean 方法获取 bean 的时候,bean 的 name 是可以以   & 开头的,即获取 FactoryBean 实例本身,此外,bean 还有别名,一个 bean 可以有多个别名等,所有在这里首先要提取 bean 的名称,即 方法 transformedBeanName

    
    final String beanName = transformedBeanName(name);
    
    protected String transformedBeanName(String name) {
        String beanName = BeanFactoryUtils.transformedBeanName(name);
        return canonicalName(beanName);
    }
    
    // 使用工具类 BeanFactoryUtils 来转名字
    public static String transformedBeanName(String name) {
        String beanName = name;
        // 如果 beanName 以 & 开头,则去掉 &
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        // 返回去掉 & 后的 beanName
        return beanName;
    }
    
    // 返回原始的bean的名字,解决别名
    public String canonicalName(String name) {
        String canonicalName = name;
        String resolvedName;
        // while 循环,因为 bean 的别名可以有多个
        do {
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }
    

    2. 尝试从缓存中获取 bean 实例

    
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        // 处理 FactoryBean
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    
    // 获取 bean
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 从缓存中获取bean,该缓存singletonObjects用来存放已经创建完毕的bean的实例
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果缓存中没有,且该 bean 正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) { 
                // 从正在创建bean的缓存中获取,该 earlySingletonObjects 缓存是用来存放正在创建且还没有创建完毕的bean
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 如果此时还是获取不到实例,且允许从ObjectFactory中获取,解决循环引用
                if (singletonObject == null && allowEarlyReference) {
                    // 从 ObjectFactory 中获取对应的工厂,使用工厂创建创建对象,因为之前在创建该bean的时候且还没有创建完毕的时候,已经把该bean的 ObjectFactory 放入到缓存中
                    ObjectFactory? singletonFactory = this.singletonFactories.get(beanName);
                    // 获取到工厂之后,进行创建bean的实例,并放入到对应的缓存中
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        // 如果缓存中没有,且该bean没有正在创建,则直接返回 nul
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
    

    在该方法里面会尝试解决循环依赖,该方法会涉及到 3 个 map 类型的缓存:

  • 缓存 `singletonObjects` 用来存放已经创建完毕的bean的实例
  • 缓存 `earlySingletonObjects` 是用来存放正在创建且还没有创建完毕的bean
  • 缓存 `ObjectFactory` 用来存放对应的工厂,因为之前在创建该bean的时候且还没有创建完毕的时候,已经把该bean的 `ObjectFactory` 放入到缓存中
  • 所以上述方法的主要逻辑就是先从 singletonObjects 获取实例,如果获取不到,即该 bean 还没有创建;再从 earlySingletonObjects 获取,如果获取不到,即该bean没有正在创建,再从 ObjectFactory 获取对应的工厂来创建,如果到最后还是获取不到,则返回 null

    3. 处理 FactoryBean

    获取到 bean的实例后,需要处理 诸如 FactoryBean factory-method 之类的方法,在后面从不同的 score 获取到 bean 的实例后,都会执行该方法:

    
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    
        // 如果 bean 的实例不是 FactoryBean 类型,即是一般的 bean ,可以直接返回
        // 如果 beanName 是以 & 开头,则也直接返回,因为 beanName 以 & 开头,表示返回工厂实例本身
        // BeanFactoryUtils.isFactoryDereference : name != null && name.startsWith("&")
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }
    
        Object object = null;
        if (mbd == null) {
            // 尝试从 FactoryBean 缓存中获取bean
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // 到这里,已经明确了 bean的实例一定是 FactoryBean 类型
            FactoryBean? factory = (FactoryBean?) beanInstance;
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
    // 通过 FactoryBean 来获取 bean 实例
    protected Object getObjectFromFactoryBean(FactoryBean? factory, String beanName, boolean shouldPostProcess) {
        // 忽略了其他代码
        // doGetObjectFromFactoryBean - factory.getObject(),返回的是 FactoryBean 的 getObject 方法的返回值
        object = doGetObjectFromFactoryBean(factory, beanName);
        return object;
    }
    

    4. 创建bean

    经过了上述几步,发现从缓存中还不到实例的话,就会进行 bean 的实例化。当时在创建之前,如果该 bean 有依赖的 bean,则先会处理依赖的bean:

    4.1 处理依赖的 bean
    
    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
        for (String dep : dependsOn) {
            if (isDependent(beanName, dep)) {
                throw new BeanCreationException("循环依赖异常");
            }
            // 注册循环依赖
            registerDependentBean(dep, beanName);
            // 创建依赖的 bean
            getBean(dep); // return doGetBean(name);
        }
    }
    
    4.2 创建 bean
    
    if (mbd.isSingleton()) {
        // 创建单例的bean
        sharedInstance = getSingleton(beanName, new ObjectFactoryObject() {
            @Override
            public Object getObject() throws BeansException {
                return createBean(beanName, mbd, args);
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    else if (mbd.isPrototype()) {
        // 创建原型的bean 
        Object prototypeInstance = null;
        try {
            beforePrototypeCreation(beanName);
            prototypeInstance = createBean(beanName, mbd, args);
        }
        finally {
            afterPrototypeCreation(beanName);
        }
        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    }
    else {
        // 创建其他score的bean
        String scopeName = mbd.getScope();
        final Scope scope = this.scopes.get(scopeName);
        Object scopedInstance = scope.get(beanName, new ObjectFactoryObject() {
            public Object getObject() throws BeansException {
            beforePrototypeCreation(beanName);
            try {
                return createBean(beanName, mbd, args);
            }
            finally {
                afterPrototypeCreation(beanName);
            });
            bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    }
    

    单例的 bean和其他score的bean的创建可以参考  的 createBean 方法。

    下面来看看创建原型的bean的过程:

    
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
        // 解析 class 
        Class? resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
    
        // 处理 lookup-method 和 replace-method 属性,在 “Spring 中 bean 注册的源码解析“ 从已经解析过
        mbdToUse.prepareMethodOverrides();
        // 在该方法里面会执行前置处理器和后置处理器
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        // 如果应用前置处理和后置处理器改变了bean,就直接返回,AOP功能就在此实现
        if (bean != null) {
            return bean;
        }
        // 正真创建bean
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }
    
    // 应用前置处理器和后置处理器
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        Class? targetType = determineTargetType(beanName, mbd);
        if (targetType != null) {
            // 前置处理器
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
                // 后置处理器 
                bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
        }
        // 省略其他代码
        return bean;
    }
    
    // 前置处理器
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class? beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }
    // 后置处理器
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
    

    5. 类型转换

    经过了上述的步骤之后,就会得到一个 bean 的实例,无论这个bean是单例的还是原型的,还是其他的score的,总之到这里就已经得到了 bean 的实例,得到实例之后,我们需要进行类型的转换,即 如果 bean 是一个 String,但是 requiredType 为 Integer ,则就需要进行类型的转换。

    
    if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
        return getTypeConverter().convertIfNecessary(bean, requiredType);
    }
    
    // 获取类型转换器
    public TypeConverter getTypeConverter() {
        TypeConverter customConverter = getCustomTypeConverter();
        if (customConverter != null) {
            return customConverter;
        }
        else {
            SimpleTypeConverter typeConverter = new SimpleTypeConverter();
            typeConverter.setConversionService(getConversionService());
            registerCustomEditors(typeConverter);
            return typeConverter;
        }
    }
    
    // 类型的转换
    public  T convertIfNecessary(Object value, Class requiredType, Field field){
        return doConvert(value, requiredType, null, field);
    }
    
    private  T doConvert(Object value, Class requiredType, MethodParameter methodParam, Field field){
        if (field != null) {
            return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
        }
        else {
            return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
        }
    }
    
    // 正真类型的转换
    public  T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
        Class requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
        // 自定义转换器
        PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
        ConversionFailedException conversionAttemptEx = null;
        ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
        if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) 
        {
            TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
            if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
                return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
            }
         }
       }
       // 省略其他代码
        if (requiredType != null) {
        if (convertedValue != null) {
            // 类型为 class
            if (Object.class == requiredType) {
                return (T) convertedValue;
            }
            // 类型为数组
            else if (requiredType.isArray()) {
                if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
                }
                return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
            }
            // 类型为集合
            else if (convertedValue instanceof Collection) {
                convertedValue = convertToTypedCollection((Collection?) convertedValue, propertyName, requiredType, typeDescriptor);
                standardConversion = true;
            }
            // 类型为 map
            else if (convertedValue instanceof Map) {
                convertedValue = convertToTypedMap( (Map?, ?) convertedValue, propertyName, requiredType, typeDescriptor);
                standardConversion = true;
            }
            if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
                convertedValue = Array.get(convertedValue, 0);
                standardConversion = true;
            }
            // String
            if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
                return (T) convertedValue.toString();
            }
            // String
            else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
                if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
                    Constructor strCtor = requiredType.getConstructor(String.class);
                    return BeanUtils.instantiateClass(strCtor, convertedValue);
                }
                String trimmedValue = ((String) convertedValue).trim();
                if (requiredType.isEnum() && "".equals(trimmedValue)) {
                    return null;
                }
                convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
                standardConversion = true;
            }
            // number
            else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
                convertedValue = NumberUtils.convertNumberToTargetClass(
                        (Number) convertedValue, (ClassNumber) requiredType);
                standardConversion = true;
            }
        }
        else {
            if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
                convertedValue = javaUtilOptionalEmpty;
            }
        }
        // 省略其他代码
        return (T) convertedValue;
    }
    

    到这里 通过 getBean 就能获取到一个正确的 bean 了,

    以上就是 getBean 方法的逻辑了,主要是需要知道 还可以通过 FactoryBean 来创建 bean,beanName 还可以是以 & 开头。 

    原文始发于微信公众号(Java技术大杂烩):

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

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

    原文链接:blog.ouyangsihai.cn >> Spring 的 getBean 方法源码解析


     上一篇
    Spring bean 创建过程源码解析 Spring bean 创建过程源码解析
    前言在上一篇文章    中分析了 Spring 中 bean 的注册过程,就是把配置文件中配置的 bean 的信息加载到内存中,以 BeanDefinition对象的形式存放,该对象中存放了 bean 的相关属性,下面就以 debug
    2021-04-05
    下一篇 
    你清楚这几个Spring常用注解吗? 你清楚这几个Spring常用注解吗?
    点击上方“Java知音”,选择“置顶公众号” 技术文章第一时间送达! 作者:平凡希 cnblogs.com/xiaoxi/p/5935009.html cnblogs.com/xiaoxi/p/
    2021-04-05