不知道各位还记不记得 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 正处于创建中,那么就会进行一个同步:
- 尝试从 earlySingletonObjects 中获取实例,如果获取到了就返回。
- 若仍然找不到,那么就先通过单例工厂缓存 —— 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;
}
通过上述代码,我们能够明确,这个方法中核心逻辑包含了如下几个:
- 尝试从单例缓存池中获取到实例。
- 标记 beanName 这个唯一标识对应的 bean 已经处于 created 阶段。
- 对我们之前解析出的 BeanDefinitionHolder 进行一个封装,获取到 RootBeanDefinition。
- 针对不同的 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实例的一个流程已经有了一个明确的认知,但是对于属性注入这一块还没有具体展开讲,那么在下一篇中就带来属性注入这部分逻辑的具体分析。