Spring源码学习--bean加载之单例创建和获取

bean生命周期

bean的生命周期如图所示:

入口

spring会根据scope创建不同的bean,本文主要是讲解spring如何创建和获取bean. 首先我们看看在DoGetBean()中的一段代码,这段代码时执行单例的创建,获取和实例化.代码如下面所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//如果注册表里没有该单例,则用这里定义的工厂创建单例
//为何要先创建一个工厂呢?  暂时的理解是可以提前暴露工厂然后生成对象,同时提高代码的封装性
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//留给子类实现
//AbstractAutowireCapableBeanFactory
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//销毁并抛出异常
destroySingleton(beanName);
throw ex;
}
}
});
//实例化
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

这里提供了一个局部类,即工厂类,根据beanName,bean的定义以及参数来生成对应的bean.核心代码在AbstractAutowireCapableBeanFactory的createBean中实现.这部分留给后面讲解.getObjectForBeanInstance()方法之前我们也讲过了,主要是为了看获取的bean是不是工厂方法且是否要通过该工厂方法获取对应的bean.我们首先来看getSingleton方法是如何实现bean的获取过程.

单例的获取

getSingleton() 内部采用同步方法块锁定singleObjects(存放单例的缓存)来保证线程安全.首先会尝试从缓存中获取单例,如果没有则尝试调用刚刚传入进来的工厂来创建一个bean. 在创建过程为了避免重复创建和循环依赖问题,首先会在bean创建之前告知该bean正在存在,实现过程无非就是放入一个正在创建bean缓存中.创建时直接调用工厂方法的getObject()获取实例,创建完成后从正在创建缓存中移出表示创建完成,并最终放到单例缓存中,下次获取该对象直接充缓存中获取就可以了.以下时主要核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
//创建前加入正在创建缓存中
beforeSingletonCreation(beanName);
...
singletonObject = singletonFactory.getObject();
...
//创建完成从正在创建缓存中移出
afterSingletonCreation(beanName);
...
if (newSingleton) {
//加入单例缓存中
addSingleton(beanName, singletonObject);
}

准备创建bean

如上一节讲的单例bean的获取主要是通过工厂方法来实现,即通过getObject(),在放方法内部创建bean.而getObject()方法的核心实现是createBean(),该方法留给子类实现.通过调试我们知道该方法在AbstractAutowireCapableBeanFactory实现了.
在createBean()方法中没有真正执行bean的创建,spring中有个编码风格,就是真正执行的部分都是交给了以do开头的方法.这里也是,真正创建bean的部分交给了doCreateBean(). 该方法主要时首先获取bean的class类型,然后判断类内部replace-method和lookup-method方法是否存在覆盖的方法,以及实例化的前置处理.如果没有替换最后根据相关信息生成bean.实例化实例化的前置处理给用户提供一个替换bean的机会.什么是替换bean? 意思时你可以根据beanName,bean的定义以及参数返回自己指定的一个对象,而不是spring根据beanName以及配置文件的信息生成对应的bean对象.以下时该方法的主要思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
...
//锁定class,根据设置的class属性或者根据className来解析Class ******.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
...
try {
//验证及准备覆盖的方法 ******
mbdToUse.prepareMethodOverrides();
}
...
try {
//给一个机会返回代理来替换真正的实例 ******
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//如果用户成功替换了bean就直接返回.否则表示用户没有替换按照常规路线生成bean.
if (bean != null) {
return bean;
}
}
...
//真正执行创建 bean ******
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
...
return beanInstance;
}

1) 验证覆盖方法,
其内部思想比较简单,就是计算所有replace-method和lookup-method方法中所有相同名字方法的次数,如果次数超过1说明该方法是被覆盖的.
2) 实例化的前置处理
这部分为spring提供了灵活的可拓展性,用户在这部分可以根据自己的需要改变获取的bean.在方法内部调用了applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization完成主要逻辑.

1
2
3
4
5
6
//实例化前的后处理器应用
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//实例化后的后处理器应用
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}

这两个方法主要时遍历执行所有的后置处理器,分别调用后置处理器的postProcessBeforeInstantiation和postProcessAfterInitialization方法.

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
        if (result != null) {
            return result;
        }
    }
}
0%