在上一篇博客中,我们已经对bean的加载跟着源代码完整的走了一遍,代码读起来很轻松,主要还是Spring的编程风格,它把每段代码分割成一个一个的小逻辑,使得每个逻辑处理起来都不是很负责,非常有利于我们学习。接下来,我们继续对bean实例的创建进行阅读。
Spring启动之后,如果我们不主动从里面获取bean的实例,Spring是不会主动创建实例的,所以实例的创建流程是从下面这段代码开始的
Person person = (Person) beanFactory.getBean("person");
虽然只有简单的一句,但是他后面的逻辑确是很复杂的,我们开始。
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
同样符合我们发现的规律,干活的永远都是do开头的方法,这就类似于被戴了帽子吧!
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//首先将用户传入的名字变成在IOC存储的beanName
final String beanName = transformedBeanName(name);
Object bean;
// 先按照用户要到的bean是单例来查找
Object sharedInstance = getSingleton(beanName);
//如果能从IOC容器的缓存中查到,那么这个bean一定是单例并且已经被加载过了
if (sharedInstance != null && args == null) {
...
//由于用户获得的bean可能是继承了FactroyBean的bean,所以还要进行一些验证和处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 我们假设在循环引用当中
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
...
try {
//获得一个合并的beanDefinition,其实就是复制了一个beanDefinition并且对其中缺少的属性进行填充
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//确保初始化当前bean所依赖的bean都初始化了
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
// 创建单例
if (mbd.isSingleton()) {
//创建单例的具体方法
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//创建一个单例
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
//由于用户获得的bean可能是继承了FactroyBean的bean,所以还要进行一些验证和处理
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
//由于用户获得的bean可能是继承了FactroyBean的bean,所以还要进行一些验证和处理
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
...
return (T) bean;
}
这个方法先假设要获取的bean是一个单例,如果从IOC容器中得到了实例,说明他是一个单例,调用getObjectForBeanInstance直接返回,如果没有获得到,创建一个MergedBeanDefinition根据他所定义的是单例还是多例进行bean的实例,在这个方法中还牵扯到了循环引用的问题,在这篇博客中我们就不细讲了,之后要单独写一篇博客介绍它,接下来我们先看一下怎么从IOC容器中获得单例:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从IOC容器的缓存中查找
Object singletonObject = this.singletonObjects.get(beanName);
//判断对应的单例对象是否在创建中,当单例对象没有被初始化完全(例如A定义的构造函数依赖了B对象,得先去创建B对象,或者在populatebean过程中依赖了B对象,得先去创建B对象,此时A处于创建中)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//在多线程环境中,对一级缓存上锁
synchronized (this.singletonObjects) {
//从二级缓存中获取对象
singletonObject = this.earlySingletonObjects.get(beanName);
//如果没有获得到,可能要获得的bean在三级缓存中
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;
}
这个方法中先是从一级缓存中获取实例,获取不到,再从二级缓存中获取,最后再从三级缓存中获取,Spring中设置三级缓存主要是为了解决单例的循环引用,在这里就不细讲了。
获取到了实例最终都要执行这个方法,那么我们就先来看看他是做什么的
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
...
// 如果instance不是FactoryBean实例,或者想要获取的就是FactoryBean实例,那么直接返回就好
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
//获取缓存的,通过FactoryBean暴露出来的对象
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 需要从FactoryBean中获取实例
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//如果对象是单例对象,则缓存从FactoryBean获得的对象。
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
如果我们创建的是一个FactoryBean,而用户想要bean实例,我们来看Spring是怎么处理的
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
会先尝试从缓存中获取,这个缓存中专门缓存了有FactoryBean创建的对象,找到后就直接返回了,没有还要继续处理:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//如果这个factoryBean是单例的,并且已经有了他的缓存
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
//从缓存中直接获取factoryBean创建的对象
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//没有获取到,说明缓存中没有,从factory中直接getObject
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
try {
//这个方法是交给用户用来定制处理的
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
//将获取的对象放到缓存中
this.factoryBeanObjectCache.put(beanName, object);
}
}
return object;
}
}
else {
//factoryBean是多例的,每次都要获取
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
Spring再次尝试从缓存中获取,获取不到说明缓存中真的没有了,那么就要从factoryBean中获取,获取完之后需要将这个对象放到缓存中,好了,到这用户就得到了他想要的bean实例了。接着我们看一下这个实例到底是怎么创建出来的,我们只看单例是怎么创建的,多例无非就是每次创建完后都不缓存。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
...
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
这里是创建单例的入口,从这个地方开始分析,我们会发现这段代码里有个回调函数,里卖弄有一个createBean方法,看来他是创建bean实例的核心了,那我们就先来看他:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
RootBeanDefinition mbdToUse = mbd;
// 获得我们要实例的bean的class对象
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
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 {
// 让beanpostprocessor有机会返回一个代理而不是目标bean实例。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
...
}
try {
//创建一个实例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException ex) {
...
}
}
同样,干活的还是那种戴帽子的方法doCreateBean,但是由于里面牵扯到了循环引用的问题,下一篇文章在讲,我们只需要知道在这个方法中,实例化了bean,并且进行了属性的填充。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
//锁住缓存
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
...
//创建对象之间先做一些检查
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//执行回调函数,获得创建的实例
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
...
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
将创建的实例放到缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
在这个方法中得到了创建的单例实例并且把它放到了缓存中。执行到这,最简单的实例化一个bean已经完成了,剩下的就是检查时候使用户所需要的类型。我们看一下实例化的流程:
一、指定要获取的实例的id
二、首先将用户传入的名字变成在IOC存储的beanName
三、先在缓存中查找,如果找到了说明是单例,接着进行根据用户的要求获取factoryBean或者是普通bean返回就好了,缓存中没有
四、缓存中没有,要根据用户要实例的bean是单例还是多例通过反射进行实例化,如果是单例需要添加到缓存中
这次的流程不是很复杂,但是其中牵扯到了循环引用的问题,在下一篇中,我们来单独介绍。