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

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

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

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

1、Bean 的实例化

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

Student student = defaultListableBeanFactory.getBean("student", Student.class);
复制代码

咱们深刻到 getBean() 这个方法中:ide

AbstractBeanFactory.getBean()post

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

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

//---------------------------------------------------------------------
// 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);
}
复制代码

继续深刻到 doGetBean() :spa

AbstractBeanFactory.doGetBean()prototype

这个方法的代码很是的多,咱们当下先关注从缓存获取 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实例,因而咱们能够接着深刻:

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

深刻到重载的 getgetSingleton() 方法

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 经过单例bean缓存 singletonObjects 获取到对应的实例
    // 这里的容器依然是经过 ConcurrentHashMap 来实现的
    // 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;
}
复制代码

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

@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()) {
            //....
        }
        // 将缓存中获取到的Object转换为bean实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    // 这里就是缓存池中不存在实例的逻辑了
    else {
        // 判断是不是prototype这种类型的bean正在被建立
        // 若是是, 直接抛出异常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    
        // 下面这块逻辑就是检查 BeanDefinition 是否在工厂中存在
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            //....
        }
    
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }
        
        try {
            // 获取到 BeanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);
        
            // 检查 bean 的依赖关系
            // 好比 A 依赖于 B, 那么就须要先把 B 建立出来
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                //....
            }
        
            // 真正建立 bean 实例的逻辑
            if (mbd.isSingleton()) { // 判断scope是不是singleton
                // 这里经过了 lambda 表达式来处理方法的执行
                // 首先会建立一个bean实例, 而后 getSingleton() 方法又会将建立好的 bean 实例缓存到单例缓存池
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 这里就会进行一个 bean 实例的建立流程
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        destroySingleton(beanName);
                        throw ex;
                   }
                });
                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;
}
复制代码

经过上述代码,咱们可以明确,这个方法中包含了 "建立 bean 实例"、"将实例缓存到单例缓存池中" 这两个逻辑。

咱们先假设已经成功建立出 bean 实例了,先去看看把实例放入缓存池的代码 —— getSingleton():

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的对象
            // 也就是经过lambda表达式中方法的返回值中获取到单例bean实例
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            
            // 关键是这里, 会将惟一标识、单例bean对象放入到缓存中
            if (newSingleton) {
            	addSingleton(beanName, singletonObject);
            }
    	}
    	// 最后把这个单例bean实例给返回
    	return singletonObject;
    }
}
复制代码

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

AbstractAutowireCapableBeanFactory.createBean()

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

/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    // ... 省略掉其余的逻辑, 只关心建立实例的逻辑
    
    try {
        // 这里又调用了一个 doCreateBean() 方法
    	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    	if (logger.isTraceEnabled()) {
    		logger.trace("Finished creating instance of bean '" + beanName + "'");
    	}
    	return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    	// A previously detected exception with proper bean creation context already,
    	// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
    	throw ex;
    }
    catch (Throwable ex) {
    	throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}
复制代码

咱们继续深刻到 doCreateBean() 内部的逻辑:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

    // ... 省略掉一些代码
    
    if (instanceWrapper == null) {
        // 这里就是bean真正建立的方法
        // 传入惟一标识、BeanDefinition、参数
    	instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    
    // ... 省略掉一些代码
    
    return exposedObject;
}
复制代码

继续深刻到 createBeanInstance()

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 省略掉其他代码
    
    if (resolved) {
    	if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
    	}
    	else {
    	    // 经过惟一标识、bean定义去实例化bean
            return instantiateBean(beanName, mbd);
    	}
    }

    // 省略掉其他代码
}
复制代码

继续深刻到 instantiateBean()

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        //...
    	
    	else {
    	    // 注意这里的 instantiate 方法, 继续跟进
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    	}
    	
    	//...
    }
    catch (Throwable ex) {
    	throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}
复制代码

继续深刻 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();
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    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);
                }
            }
    	}
    	// 经过 BeanUtils.instantiateClass() 进行实例化
    	// 经过反射的方式进行一个实例化
    	return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
    	// Must generate CGLIB subclass.
    	return instantiateWithMethodInjection(bd, beanName, owner);
    }
}
复制代码

2、总结

经过这篇文章的分析,咱们必需要明确如下几个关键点:

  • Spring 在获取单例对象的实例时,会先尝试从缓存池获取,这个缓存池底层经过了 ConcurrentHashMap 进行实现。
  • 若是缓存池中没有,那么会获取到 beanDefinition,而后经过这个 beanDefinition 进行实例的建立。
  • 当建立成功后会放入缓存池中,并返回相应的实例。

就哪怕我分析的代码一点都没看懂也不要紧,这几个点是必需要明确的。

那么下一篇,将带来 Spring Bean 建立策略的一个详细分析。

相关文章
相关标签/搜索