【超详细的Spring源码分析 —— 06 Spring IoC 对于 Bean 管理的核心组件分析 - 实例化 Bean Definition】

360 阅读17分钟

不知道各位还记不记得 Spring 对 bean 生命周期的管理方式:Spring 默认采用单例的方式管理 Bean,在获取 Bean 实例的时候会通过一个缓存进行获取,如果还未初始化,那么就会先将 Bean Definition 进行一个初始化放入缓存,然后再通过缓存获取。

那么在上一章中,我也在总结中提到过:在执行完 beanDefinitionReader.loadBeanDefinitions(resource); 这段代码之后,仅仅是完成了 beanDefinition 的解析与注册,还未到初始化阶段。

在这一章中,我将详细对 bean 在何时进行实例化、如何放入缓存这部分的内容进行详细的分析。

一、获取 bean 实例的入口

首先是方法入口,也就是我们获取 bean 实例的代码:

Student student = defaultListableBeanFactory.getBean("student", Student.class);

我们深入到 getBean() 这个方法中:

DefaultListableBeanFactory.getBean("student", Student.class)

可以发现,这里调用的是 AbstractBeanFactory 的 getBean() 方法,它是 DefaultListableBeanFactory 的父类。

这里分别 getBean() 方法进行了不同的重载,并且底层是调用了 doGetBean() 这个方法:

//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------

@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

@Override
public <T> T getBean(String name, Class<T> 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);
}

二、尝试从单例缓存池中获取 bean 实例

继续深入到 doGetBean() :

AbstractBeanFactory.doGetBean(String name, Class<T> requiredType)

这个方法的代码非常的多,我们当下先关注从缓存获取 bean 实例的逻辑,因此我先省略掉后续的代码:

@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
    // 获取到bean的唯一标识
    final String beanName = transformedBeanName(name);
    Object bean;
    
    // 提早地去检查缓存中是否存在相应的bean实例
    // 如果存在就返回相应的单例bean
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
    
    //....
}

上面这个方法会从单例缓存池中获取单例bean实例,于是我们可以接着深入:

AbstractBeanFactory.getSingleton(String beanName)

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

这个 getSingleton() 方法非常关键,涉及到一个循环依赖的解决方案。关于循环依赖这一块内容比较多,并且会偏离主线,后续我会单独写一篇来说明,这里我们把目光聚焦在实例化 Bean 的流程中。

首先,深入到重载的 getSingleton() 方法,这个方法存在于 AbstractBeanFactory 的父类 DefaultSingletonBeanRegistry 中:

DefaultSingletonBeanRegistry.getSingleton(String beanName, boolean allowEarlyReference)

这个方法通过了 3 层缓存进行单例的获取:

三个缓存分别对应 DefaultSingletonBeanRegistry 中定义的如下几个容器:

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

首先,会通过 singletonObjects 来获取实例对象,如果成功获取到,那么就直接返回了。

如果没有获取到,并且这个实例 bean 正处于创建中,那么就会进行一个同步:

  1. 尝试从 earlySingletonObjects 中获取实例,如果获取到了就返回。
  2. 若仍然找不到,那么就先通过单例工厂缓存 —— singletonFactories 去获取到一个单例工厂对象,然后通过这个单例工厂对象去获取实例。若成功获取到,就会将其添加到 earlySingletonObjects,然后在单例工厂缓存中删除对应的工厂实例。

具体代码如下所示:

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 通过单例bean缓存 singletonObjects 获取到对应的实例
    // key=唯一标识、value=单例bean实例
    Object singletonObject = this.singletonObjects.get(beanName);
    
    // 如果发现缓存中不存在对应的bean实例, 并且发现这个bean正处于创建过程中
    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;
}

对于 isSingletonCurrentlyInCreation 这个参数,我有必要单独说明一下,它会判断对应的单例对象是否在创建中,当单例对象没有被完全创建时,比如A类依赖于B类,那么就需要先创建B类的实例,此时实例A就处于一个创建中的状态。

这里我们先留个眼熟,大概知道 Spring 在通过单例缓存池获取实例时,会经过三层缓存尝试获取,如果都没有,才会对 bean 实例进行创建。

三、创建实例流程分析

我们回到 doGetBean() ,看看后续会进行什么逻辑:

AbstractBeanFactory.doGetBean(String name, Class<T> requiredType)

@SuppressWarnings("unchecked")
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);
    Object bean;

    // 如果缓存池中存在相应的实例, 在这里就会直接进行返回
    // 没有的话就会返回一个空值
    Object sharedInstance = getSingleton(beanName);
   
    // 如果成功从单例缓存池中获取到了实例
    if (sharedInstance != null && args == null) {
        // 紧接着去打印一下日志
        if (logger.isTraceEnabled()) {
            //....
        }
        // 这个方法涉及到 AOP 相关的内容
        // 目前, 简单理解为将缓存中获取到的Object转换为bean实例即可
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        
    } // 如果是走这个逻辑,之后会进行一个类型检查, 之后就能够返回实例了
    
    // 这里就是缓存池中不存在实例的逻辑了
    else {
        // 判断是否是prototype这种类型的bean正在被创建
        // 如果是, 直接抛出异常, 防止多线程同时创建Bean
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    
        // 下面这块逻辑就是检查 BeanDefinition 是否存在于父工厂
        // 如果不为空且 BeanDefinition 存在, 紧接着就会对各种参数进行一个校验
        // 这里不是我们的重点
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            //....
        }
    
        // 是否只进行类型检查, 默认是false
        if (!typeCheckOnly) {
            // 这个方法把对应的bean标记为created, 表示即将创建或已经创建
            // 从而避免一个重复的 bean 创建
            // 就比如一个bean在创建过程中,又接收到一个创建该bean的请求
            // 那么通过这个标记就能够避免重复的创建流程
            // 底层实现就是通过一个ConcurrentHashMap转换的Set来存储bean的唯一标识
            markBeanAsCreated(beanName); 
        }
        
        try {
            // 获取到一个RootBeanDefinition, 可以将其简单理解为Bean的汇总信息
            // 它内部还封装了 BeanDefinitionHolder
            // 而 BeanDefinitionHolder 主要包含了beanName、beanDefinition
            // 简单来说,我们之前在xml中解析出的Bean定义在这里就被获取到了
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 检查mbd是否是抽象的, 因为抽象类无法被实例化
            // 因此如果是抽象, 则会抛出一个异常
            checkMergedBeanDefinition(mbd, beanName, args);
        
            // 检查 bean 的依赖关系
            // 比如 A 依赖于 B, 那么就需要先把 B 创建出来
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                //....
            }
        
            // 真正创建 bean 实例的逻辑
            if (mbd.isSingleton()) { // 判断scope是否是singleton
                // 这里通过了 lambda 表达式来处理方法的执行
                
                // 执行的 getSingleton() 就是之前通过缓存获取 bean 实例那个方法的重载
                // 这个 getSingleton() 会接受beanName、ObjectFactory作为参数
                // ObjectFactory 是一个接口, 它内部有且仅有一个 getObject() 方法用于返回实例 
                // 那么整个执行流程就是:
                // 1. 执行 getSingleton(), 然后在调用到ObjectFactory这个参数的时候,执行lambda中的逻辑
                // 2. 创建 ObjectFactory, 这个工厂中就包含了bean实例
                // 3. 调用 ObjectFactory.getObject() 获取到实例执行后续 getSingleton() 方法的逻辑
                
                // 一会儿我们会详细对 getSingleton()、createBean() 这两个方法的逻辑进行详细的分析
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 这里就会进行一个 bean 实例的创建流程
                        // 然后返回一个 ObjectFactory 实例
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        destroySingleton(beanName);
                        throw ex;
                   }
                });
                // 依旧是一个 object -> bean 实例的转换
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            // 判断scope是否是prototype
            else if (mbd.isPrototype()) {
                // ....省略
            }
            else { // 这边就是其他scope类型的bean实例化的逻辑
                // ....省略
            }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }
    
    // ...省略
    return (T) bean;
}

通过上述代码,我们能够明确,这个方法中核心逻辑包含了如下几个:

  1. 尝试从单例缓存池中获取到实例。
  2. 标记 beanName 这个唯一标识对应的 bean 已经处于 created 阶段。
  3. 对我们之前解析出的 BeanDefinitionHolder 进行一个封装,获取到 RootBeanDefinition。
  4. 针对不同的 scope,进行不同的实例创建流程。

这个方法就包含了创建实例bean、对实例bean赋值、并添加到缓存的逻辑,下面我们具体来看创建实例bean的逻辑:

深入到 getSingleton()

DefaultSingletonBeanRegistry.getSingleton(String beanName, boolean allowEarlyReference)

这个方法依然是 DefaultSingletonBeanRegistry 中定义的重载方法,它需要接受一个 beanName、一个对应的单例工厂实例,这个单例工厂实例能够返回一个 bean 实例。

当调用到 singletonFactory 时,会执行 AbstractBeanFactory.doGetBean() 这个方法中 lambda 表达式里的逻辑,来创建一个单例工厂实例:

/**
 * 返回一个通过给定名称被注册的单例对象
 * 若还未被注册, 那么就执行创建、注册的逻辑, 再返回
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    // 首先对单例缓存池(一级缓存)进行一个加锁
    synchronized (this.singletonObjects) {
        // 首先尝试从单例缓存池中获取
    	Object singletonObject = this.singletonObjects.get(beanName);
    	if (singletonObject == null) {
            // ... 省略逻辑我们不需要太关心, 就是一些异常、日志处理
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(...);
            }
            if (logger.isDebugEnabled()) {
                logger.debug(...);
            }
            // 初始化实例前的前置处理
            beforeSingletonCreation(beanName);
            // 如果成功创建了,这个标识就会被置为true
            boolean newSingleton = false;
            
            // 非重点
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
            	this.suppressedExceptions = new LinkedHashSet<>();
            }
            
            try {
                // 尝试通过singletonFactory来获取实例
                // 这里就会执行 lamda 中的逻辑了
            	singletonObject = singletonFactory.getObject();
            	newSingleton = true;
            }
            catch (Exception ex) {
            	// 异常处理我们忽略...
            }
		
            finally {
            	if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
            	}
            	// 后置处理
            	afterSingletonCreation(beanName);
            }
            
            // 当 newSingleton 标识为 true, 就意味着bean实例已经成功创建了
            if (newSingleton) {
                // 这个逻辑就是将实例添加到缓存中
                // 这个方法我们会在整个初始化阶段结束后再分析
            	addSingleton(beanName, singletonObject);
            }
    	}
    	// 最后把这个单例bean实例给返回
    	return singletonObject;
    }
}

我们深入一下单例 bean 创建实例,也就是lambda表达式中的代码:java createBean(beanName, mbd, args); 的执行过程:

AbstractAutowireCapableBeanFactory.createBean()

AbstractAutowireCapableBeanFactory 这个类同样是 DefaultListableBeanFactory 的父类:

/**
 * 创建bean实例、执行装配bean实例、运用后置处理器等
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    
    RootBeanDefinition mbdToUse = mbd;

    // 解析bean的Class对象
    // 这个Class对象就会用于bean的实例化
    // 在这个方法里面, 我们之前解析并创建 AbstractBeanDefinition 时获取到的 ClassLoader 或 全限定类名就会在这里使用
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    
    // 然后就会将 Class 对象set到RootBeanDefinition上
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }
    
    // Prepare method overrides.
    try {
    	mbdToUse.prepareMethodOverrides();
    } catch (BeanDefinitionValidationException ex) {
    	// ... 
    }

    try {
    	// 后置处理器中的一些处理
    	// 使得我们可以返回 bean 本身,也可以返回一个代理对象
    	// 这里就是代理相关的逻辑
    	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    	// 如果代理后的bean不为空, 就直接返回了
    	if (bean != null) {
    		return bean;
    	}
    } catch (Throwable ex) {
    	throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex);
    }

    // 真正创建bean实例的逻辑
    try {
        // 深入
    	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    	// 打印日志
    	if (logger.isTraceEnabled()) {
    		logger.trace("Finished creating instance of bean '" + beanName + "'");
    	}
    	// 返回实例
    	return beanInstance;
    }
    catch (Exception e) {
        // 省略....
    }
}

我们继续深入到 doCreateBean() 内部的逻辑:

AbstractAutowireCapableBeanFactory.doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
    
    // Bean的包装器, 对bean的一层封装, 增加了一些额外的描述信息
    // 这里也是跟之前封装 Resource -> EncodedResource 是同一种思路
    // 体现了面向对象的封装特性
    BeanWrapper instanceWrapper = null;
    
    // 真正创建对象时,会把factoryBeanInstanceCache这个缓存中的键值对移除
    // 当然,如果我们从未创建过 BeanWrapper 实例, 那么这里是会返回null的
    // 底层依然通过了 ConcurrentHashMap 来实现这个缓存
    if (mbd.isSingleton()) {
    	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    
    // 这里就是创建bean实例, 这里返回的类型就是 BeanWrapper
    if (instanceWrapper == null) {
        // 对于这个方法, 我们下面会深入
        // 当这个方法执行完成之后, 我们会获取到一个属性都为空的一个实例
        // 那么在后续的逻辑, 就涉及到属性注入相关的内容了
    	instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    
    // 返回出 BeanWrapper 中封装的bean实例
    final Object bean = instanceWrapper.getWrappedInstance();
    
    // 获取到 Bean 的类型
    Class<?> beanType = instanceWrapper.getWrappedClass();
    
    // 如果类型不是一个 NullBean, 那么在 RootBeanDefinition 中设置上相应的属性
    if (beanType != NullBean.class) {
    	mbd.resolvedTargetType = beanType;
    }
    
    // 这里就是一个后置的处理, 可以忽略
    synchronized (mbd.postProcessingLock) {
    	// ...
    }
    
    // 尽早地缓存这个bean实例, 以解决循环引用的问题
    // 这里就需要回忆一下前面的三层循环了
    // 判断是否是单例(只有单例才会被缓存)、是否允许循环引用、当前bean是否处于一个created状态
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    		isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
    	if (logger.isTraceEnabled()) {
            // 日志打印我们可以忽略
    	}
    	// 这里就会对单例缓存池进行一个处理, 内部就是解决循环依赖的核心逻辑
    	// 需要注意的是, 到这一步, 并没有将实例放入第一层缓存(singletonObjects)中
    	// 内部的逻辑是:
    	// 若 singletonObjects 不包含对应的bean
    	// 那么就在三级缓存 singletonFactories 放入对应的 singletonFactory 实例
    	// 并且在二级缓存 earlySingletonObjects 中移除 key=beanName 的键值对
    	// 然后 registeredSingletons 中添加相应的 beanName, 表示相应的单例已经被注册了
    	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    
    // 获取到刚被初始化的Bean实例
    Object exposedObject = bean;
    try {
        // 这个方法中, 就封装了注入属性的一个逻辑
        // 里面的逻辑结构非常深, 针对属性注入我会单独写一篇来讲
        // 这边大概知道, 在这里会进行属性注入即可
    	populateBean(beanName, mbd, instanceWrapper);
    	
    	// 初始化给定的bean实例
    	exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
    	// 省略异常逻辑
    }
    
    if (earlySingletonExposure) {
    	//... 省略这部分的逻辑
    }
    
    // 注册bean销毁时的一些逻辑
    try {
    	registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
    	// ...
    }
    
    return exposedObject;
}

继续深入到 createBeanInstance()

AbstractAutowireCapableBeanFactory.createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

// 通过不同的创建策略(比如工厂方法、构造器注入、简单实例化)来创建出指定的bean实例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 确保 Class 能够成功获取到
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
    // 若 Class 不为空, 且访问修饰符是非public, 且非public不允许访问
    // 这里就会抛出一个异常
    // 其实第二个条件 Spring 都能通过反射机制提供的setAccessible(true)来解决
    // 主要是第三个条件为true时, 就无法实例化了
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    	throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
    
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
    	return obtainFromSupplier(instanceSupplier, beanName);
    }
    
    if (mbd.getFactoryMethodName() != null) {
    	return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    
    // Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
    	// 省略...
    }
    if (resolved) {
    	// 省略...
    }
    
    // 获取到能够使用的构造器方法对应的实例对象数组
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    		mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    	return autowireConstructor(beanName, mbd, ctors, args);
    }
    
    // 获取到优先构造器, 一般情况下是默认构造
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
    	return autowireConstructor(beanName, mbd, ctors, null);
    }
    
    // 若没有指定构造器, 那么使用null-args的构造器
    // 我们继续跟进这个方法
    return instantiateBean(beanName, mbd);
}

继续深入 instantiateBean()

AbstractAutowireCapableBeanFactory.instantiateBean()

/**
 * 使用默认构造器进行实例化bean
 */
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
    	Object beanInstance;
    	final BeanFactory parent = this;
    	// 检查系统的安全管理器
    	if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
    				getInstantiationStrategy().instantiate(mbd, beanName, parent),
    				getAccessControlContext());
    	}
    	else { // 这里就已经创建出bean实例了
    	    // 这里就通过获取到策略实例, 然后调用instantiate()进行了实例化
    	    // 不同的策略有不同的实例化方式
    	    // 一般是采用cglib
    	    // 我们会深入到 instantiate() 看看具体的逻辑
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    	}
    	// 然后将这个实例封装到 BeanWrapper
    	BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    	// 封装一些额外的描述信息到 BeanWrapper 实例
    	initBeanWrapper(bw);
    	// 返回一个包含了bean实例、额外信息的BeanWrapper
    	return bw;
    }
    catch (Throwable ex) {
    	// ...
    }
}

深入到 instantiate():

SimpleInstantiationStrategy.instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)

不同的实例化策略会调用不同的instantiate()方法。

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
    if (!bd.hasMethodOverrides()) {
    	Constructor<?> constructorToUse;
    	synchronized (bd.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                
            	final Class<?> clazz = bd.getBeanClass();
            	// 判断 Class 类型是否是一个接口
                // 接口是无法实例化的
            	if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
            	}
            	try {
            	    // 如果配置了检查器,通过检查器进行检查
            	    // 一般情况下都是 null
                    if (System.getSecurityManager() != null) {
                    	constructorToUse = AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    }
                    else { // 获取到待使用的构造方法实例
                    	constructorToUse = clazz.getDeclaredConstructor();
                    }
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            	}
            	catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            	}
            }
    	}
    	// 通过一个工具类, 传入构造方法进行一个实例化
    	// 这个工具类在之前解析Bean时, 创建 BeanDefinitionDocumentReader 这个文档读取器时也有用过
    	// 只不过当时是通过传入 Class 对象进行实例化
    	return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
    	// Must generate CGLIB subclass.
    	return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

深入到 BeanUtils.instantiateClass(constructorToUse)

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
    Assert.notNull(ctor, "Constructor must not be null");
    try {
    	ReflectionUtils.makeAccessible(ctor);
    	
    	// kotlin这一块我们不需要管
    	if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
    		return KotlinDelegate.instantiateClass(ctor, args);
    	}
    	else {
    	    // 获取到构造方法参数
            Class<?>[] parameterTypes = ctor.getParameterTypes();
            Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
            // 这里就是对参数进行一个处理
            Object[] argsWithDefaultValues = new Object[args.length];
            for (int i = 0 ; i < args.length; i++) {
            	if (args[i] == null) {
                    Class<?> parameterType = parameterTypes[i];
                    argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
            	}
            	else {
                    argsWithDefaultValues[i] = args[i];
            	}
            }
            // 这里本质上就调用了反射中Constructor这个类的newInstance()方法进行一个实例化
            // 当走到这里, 对象的创建工作就完成了
            return ctor.newInstance(argsWithDefaultValues);
    	}
    }
    // 省略了异常处理的逻辑
    catch (Exception ex) {
    	//...
    }
}

四、添加实例到缓存分析

我们回到 getSingleton() 方法的末尾部分:

DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    // 首先对单例缓存池(一级缓存)进行一个加锁
    synchronized (this.singletonObjects) {
        // 首先尝试从单例缓存池中获取
    	Object singletonObject = this.singletonObjects.get(beanName);
    	if (singletonObject == null) {
            // 省略掉之前创建Bean实例的代码...

            // 当 newSingleton 标识为 true, 就意味着bean实例已经成功创建了
            if (newSingleton) {
                // 这个逻辑就是将实例添加到缓存中
                // 这个方法我们会在整个初始化阶段结束后再分析
            	addSingleton(beanName, singletonObject);
            }
    	}
    	// 最后把这个单例bean实例给返回
    	return singletonObject;
    }
}

深入到 addSingleton() 这个方法:

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

整个代码逻辑非常简单,就是一堆容器的put、remove操作。这里往一级缓存 singletonObjects 中放入了完整创建好的bean实例,二级 singletonFactories、三级 earlySingletonObjects 缓存中移除相应的 k-v,并且在一个标识 "已经注册的单例" 容器中添加上相应的 beanName。

到这里,整个实例化 Bean 并获取到相应 Bean 的流程就结束了。

五、总结

通过这篇文章的分析,我们必须要明确以下几个关键点:

  • Spring 在获取 单例对象 的实例时,会先尝试从单例缓存池获取。
  • 如果缓存池中没有,那么会进行一个 bean 实例的创建工作。
  • 当创建成功后会放入缓存池中,并返回相应的实例。

在以上 "bean实例创建" 的这个过程中,会先创建一个属性未被注入的bean,然后再进行一个依赖注入,两个过程是分开的。

通过这一章我们已经对创建bean实例的一个流程已经有了一个明确的认知,但是对于属性注入这一块还没有具体展开讲,那么在下一篇中就带来属性注入这部分逻辑的具体分析。