spring源码学习一: bean的加载

1 吐槽

学spring,用spring,天天围绕着这么一个框架转;Autowired,Resource,Service,Controller,Repository,各种注解都写了不下千遍,敲代码得速度可能比菜市场的老大妈算菜钱的心算速度都要快了;樱花下落的速度是五厘米每秒,我敲注解的手速是1分钟30个。。。。。

然而代码敲了很多,始终停留在应用层面,而且是很粗浅的日常使用罢了,就像老大妈只知道一斤菠菜3.2块钱,3斤菠菜就是9.6块一样,虽心算速度直逼计算机,却不知这种程度的计算在整个数学的菜单里,就像一盘菜里的大蒜葱花一般,是基础,但是也就只是基础,不算一道完整菜。

于是,神(我自己)说,要有源码。

所以,就有了源码的学习。

(PS:本文的思路和内容都是源自于郝佳大佬写的《spring源码深度解析《(第2版)》一书,个人只是学习总结和记录,如果对源码有兴趣,可以买书支持一下!!!)

2 切入点

2.1 切入点

AbstractBeanFactory 中的 getBean() 方法。

一般在学spring的时候,比如学习spring过程中写的demo里,需要从容器中拿一个bean,经常出现对如下这个方法的使用,大致是这样的:

ApplicationContext app = new AnnotationConfigApplicationContext(xxxConfig.class);
app.getBean("一个bean");

看起来很普通的从new出来的spring容器中拿了一个bean而已,一个七个字母的方法,其实就内部的源码里就包含了对bean的加载过程。

跟进,其源码如下:

	public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

这里剧透一下,在日后窥探spring源码精髓的过程中,可能会发现一些规律,那就是一个真正的干活函数,往往是以do开头的,如 getBean 中的 doGetBean 方法;而这些表面上看起来在干活的函数,如 getBean,只做一些统筹全局的工作,并调用这些真正的干活函数。

跟进 doGetBean 方法:

    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    	//注释1-----------------------------------------------------------------------
        String beanName = this.transformedBeanName(name);
        //注释2-----------------------------------------------------------------------
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            if (this.logger.isDebugEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
			 //注释3----------------------------------------------------------------------
            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
        
        	//注释4----------------------------------------------------------------------
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            
			//注释5----------------------------------------------------------------------
            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }

                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
          		 //注释6----------------------------------------------------------------------
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                
				//注释7----------------------------------------------------------------------
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }

                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }
				
				//注释8----------------------------------------------------------------------
                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    var11 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                	//注释8----------------------------------------------------------------------
                    String scopeName = mbd.getScope();
                    Scope 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, () -> {
                            this.beforePrototypeCreation(beanName);

                            Object var4;
                            try {
                                var4 = this.createBean(beanName, mbd, args);
                            } finally {
                                this.afterPrototypeCreation(beanName);
                            }

                            return var4;
                        });
                        bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var23) {
                        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", var23);
                    }
                }
            } catch (BeansException var26) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var26;
            }
        }

        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                } else {
                    return convertedBean;
                }
            } catch (TypeMismatchException var25) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
                }

                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        } else {
            return bean;
        }
    }

当场懵逼。这个方法怎么这么长?这些变量、参数都是谁?他们凑在一起在干嘛?我可以退出源码学习吗?

莫急,一一拆开来,先从大致流程来,看看spring都做了些啥。

2.2 这个方法做了什么?

1)转换对应的beanName (注释1处)

 String beanName = this.transformedBeanName(name);

在我初步学习的时候,就曾对此表示疑问:我从外部传进来的不就是beanName吗?为何还要转换?

确实,一般来说是传进来的beanName,但是也有其他情况,比如别名,或者想要FactoryBean而不是其中的对象,此时传入的可不是我们常用的beanName了。

这里插一句,想要获得FactoryBean,是这样的,此时才能拿到装着bean的FactoryBean:

app.getBean("&bean")

2)尝试从缓存中加载单例 (注释2处)

Object sharedInstance = this.getSingleton(beanName);

如标题意思所述。

3)获取bean的实例 (注释3处)

bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);

从前几行的if语句中可以看出,缓存中是存在该bean的,但是spring缓存中记录的是bean的初始状态,并不一定是我们想要的最终的bean,spring需要对其再加工一下变成我们真正需要的bean,而 getObjectForBeanInstance 就是用来完成这一工作的函数;

4)对非单例bean的检查 (注释4处)

  if (this.isPrototypeCurrentlyInCreation(beanName)) {
       throw new BeanCurrentlyInCreationException(beanName);
    }

if 判断中的方法名为:isPrototypeCurrentlyInCreation,字面意思呢,就是正在创建中的多例bean;

具体什么意思?就是我们在 getBean 方法中传入的beanName所指向的那个bean,还在创建呢,而且是多例的,对于多例的bean,不会在容器启动时创建,其只有在被调用时才创建,所以此时不能拿。此时,spring也不知道该干嘛了,就报个错吧。

5)检测parentBeanFactory (注释5处)

 			BeanFactory parentBeanFactory = this.getParentBeanFactory();
 			
 			//如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName,则尝试去父类工厂中检测
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }

                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }

缓存中没有,配置里也没有所需的bean,就尝试去父类工厂里加载bean;

6)将配置中GenericBeanDefinition 转换为 RootBeanDefinition (注释6)

 RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);

spring把从配置中拿到的bean信息存储在了 GenericBeanDefinition 中,但是doCreateBean这个方法中处理的是 RootBeanDefinition ,所以需要转换一下,同时若这个bean有父类,则顺带合并一哈。

7)寻找依赖 (注释7)

			String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }

                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }

在bean初始化的时候,可能会用到一些属性,且这些属性的配置依赖于其他的bean,那么这时,需要先初始化bean所需的依赖。 注意是初始化。

8) 对不同的scope的bean进行创建 (注释8)

见代码。

3 详解:

3.1 从缓存中获取单例bean

3.1.1 尝试从缓存中获取

虽说是获取,但是也只是尝试获取,获取不到就算了。

这里提一句,spring为了避免循环依赖,会在bean还未创建完成时,便把创建bean时对应的ObecjtFactory曝光到缓存,以便其他需要该bean的对象引用;

获取单例bean时,先尝试从缓存中加载,如果失败,则再尝试从singletonFactories中加载ObecjtFactory

上代码:

//
@Nullable
    public Object getSingleton(String beanName) {
        return this.getSingleton(beanName, true);  //true 为allowEarlyReference
    }

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject;
    }

这段代码里,怎么这么多xxxxxxObjects? 看的头疼。

这里面出现的几个map,到底是有什么用嘞?都代表什么含义?

singletonObjects:用于保存beanName和bean实例;
singletonFactories: 保存beanName和创建bean的工厂,ObecjtFactory就存在这里;
earlySingletonObjects: 保存beanName和bean实例,但是可以在bean创建过程中被拿到;
顺带一提,registeredSingletons: 保存当前所有已注册的bean

那么这一段代码的作用,简单来说就是:1 尝试从singletonObjects拿创建好的bean,如果有,返回;

如果没有—》2 从earlySingletonObjects查找有没有所需bean,如果有,返回;

如果还没有-------》3 从singletonFactories拿半成品bean,即ObjectFactory,从而拿到bean;

3.1.2 缓存中获取成功,进一步获取bean实例

接下来,就是详细阅读源码的部分了。话不多说,先来源码提提神:

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            
			//  1 验证FactoryBean,同时非FactoryBean的不处理
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
            }
        }

        if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
            Object object = null;
            if (mbd == null) {
                object = this.getCachedObjectForFactoryBean(beanName);
            }

            if (object == null) {
                FactoryBean<?> factory = (FactoryBean)beanInstance;
                if (mbd == null && this.containsBeanDefinition(beanName)) {
                    mbd = this.getMergedLocalBeanDefinition(beanName);
                }

                boolean synthetic = mbd != null && mbd.isSynthetic();
                
                //	2 将从FactoryBean中获取bean的工作交给getObjectFromFactoryBean处理;
                object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
            }

            return object;
        } else {
            return beanInstance;
        }
    }

简单梳理一下这个方法都干了啥:

1 验证FactoryBean,同时非FactoryBean的不处理
2 将从FactoryBean中获取bean的工作交给getObjectFromFactoryBean处理;

这个方法的重点就在于getObjectFromFactoryBean如何把所需bean解析出来。

所以,跟进getObjectFromFactoryBean:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        if (factory.isSingleton() && this.containsSingleton(beanName)) {
            synchronized(this.getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    object = this.doGetObjectFromFactoryBean(factory, beanName);
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    } else {
                        if (shouldPostProcess) {
                            if (this.isSingletonCurrentlyInCreation(beanName)) {
                                return object;
                            }

                            this.beforeSingletonCreation(beanName);

                            try {
                                object = this.postProcessObjectFromFactoryBean(object, beanName);
                            } catch (Throwable var14) {
                                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var14);
                            } finally {
                                this.afterSingletonCreation(beanName);
                            }
                        }

                        if (this.containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }

                return object;
            }
        } else {
            Object object = this.doGetObjectFromFactoryBean(factory, beanName);
            if (shouldPostProcess) {
                try {
                    object = this.postProcessObjectFromFactoryBean(object, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var17);
                }
            }

            return object;
        }
    }

代码一长,老实说就有点抗拒。但是看源码,不是一行一行的看懂每一个字才算看懂,要学会看到其关键方法和步骤。

前面说过,开头带do的,往往是干活的函数。而在这个方法里,正好就有一个do开头的方法,就是doGetObjectFromFactoryBean方法。

根据经验,这里大概率就是真正从FactoryBean里拿到所需bean的方法了。

跟进doGetObjectFromFactoryBean:

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
        Object object;
        try {
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = this.getAccessControlContext();

                try {
                    object = AccessController.doPrivileged(factory::getObject, acc);
                } catch (PrivilegedActionException var6) {
                    throw var6.getException();
                }
            } else {
                object = factory.getObject();    //关键一行
            }
        } catch (FactoryBeanNotInitializedException var7) {
            throw new BeanCurrentlyInCreationException(beanName, var7.toString());
        } catch (Throwable var8) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
        }

        if (object == null) {
            if (this.isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
            }

            object = new NullBean();
        }

        return object;
    }

这么多行的代码,其实关键的一行看到即可。

object = factory.getObject();

了解FactoryBean的应该懂了哈。这里就是为了拿到FactoryBean里的对象。其他的代码,都是对参数的一些修饰判断罢了。

回过头来看的话,其实这个方法的名字,已经把他要做的事都实话实说了。

3.2 缓存中没有,开始创建单例bean

在上面2.1中doGetBean方法的第一个注释8的位置,有如下一段代码:

if (mbd.isSingleton()) {
     sharedInstance = this.getSingleton(beanName, () -> {
          try {
              return this.createBean(beanName, mbd, args);
          } catch (BeansException var5) {
              this.destroySingleton(beanName);
              throw var5;
          }
      });
      bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 }

可以看到,对于缓存中没有的单例bean,这里也用了一个叫getSingleton的方法去获取,只不过使用的不是从缓存中取bean时提到的getSingleton方法,而是同名的另一个重载方法。

这里先不看createBean方法,而是先进入这个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);
            
			//	1 检查这个bean在缓存中有没有;
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                
			//	2 beforeSingletonCreation记录加载状态;
                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }
			
                try {
                //	3 由于传入的singletonFactory其类型为ObjectFactory,所以这里singletonFactory.getObject()是在获取bean;
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                //   4 将结果添加到缓存并删除加载过程中的各种辅助记录
                    this.addSingleton(beanName, singletonObject);
                }
            }
			//  5 返回处理结果
            return singletonObject;
        }
    }

又是一大段代码。。。。。。

总结一下这段代码,其主要做了如下5步内容:

	1 检查这个bean在缓存中有没有;
	2 beforeSingletonCreation记录加载状态;
    3 由于传入的singletonFactory其类型为ObjectFactory,所以这里singletonFactory.getObject()是在获取bean;
	4 addSingleton(beanName, singletonObject)加入缓存;
	5 返回singletonFactory.getObject()获取到的bean;

这里有个要留意的点:singletonFactory是哪里来的呢?

方法的参数之一提供的。

类型呢?=======》ObjectFactory<?>

有没有很熟悉呢? 在3.1.1中,有提到这个类型的用处。

接下来,就是继续探索产生singletonFactory的方法=====》 createBean 方法了。

3.3 准备创建bean

进入createBean方法,又是一长串代码。具体源码如下:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Creating instance of bean '" + beanName + "'");
        }

        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        try {
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var9) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
        }

        Object beanInstance;
        try {
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var10) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
        }

        try {
            beanInstance = this.doCreateBean(beanName, mbdToUse, args);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Finished creating instance of bean '" + beanName + "'");
            }

            return beanInstance;
        } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
            throw var7;
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
        }
    }

那么这里还是整理下这个方法的主要工作。这段代码,可以简化为如下的代码:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        ~~~~~~~~~~~~巴拉巴拉巴~~~~~~~~~~~~~~~~
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]); //锁定class,根据设置的class属性或className解析class;
        
        try {
            mbdToUse.prepareMethodOverrides(); //对override属性进行标记及验证;
        } catch (~~~~~~~~~ {
				~~~~~~~~~~~~~
        }

        Object beanInstance;
        try {
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse); //跟beanProcessor一个机会返回代理,该代理会代替真正的实例;
            if (beanInstance != null) {
                return beanInstance;
            }
           ~~~~~~~~
        } catch (~~~~~~~~~~~) {
          ~~~~~~~~~~~~~~~~~
        }

        try {
            beanInstance = this.doCreateBean(beanName, mbdToUse, args); //do开头,这个方法就是创建bean的真正方法;
           ~~~~~~~~~~~~~~~
            return beanInstance;
        } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
            throw var7;
        } ~~~~~~~~~~~~~
    }

this.resolveBeforeInstantiation(beanName, mbdToUse) 方法,看其方法名称,叫给个机会,是在创建bean前出现。如果这个方法的返回值不为null,则直接会返回beanInstance,从而不进行bean的创建。其内部代码为:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = this.determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }

            mbd.beforeInstantiationResolved = bean != null;
        }

        return bean;
    }

这个方法,基本就是对后置处理的调用;

同时,resolveBeforeInstantiation这个方法和其下的判断,也和AOP有关;

3.4 循环依赖

1 循环依赖的定义:

两个或多个bean互相持有对方;例如A类中有成员变量B类,B类中有成员变量C类,C类中又有成员变量A类。

2 三种循环依赖的情况以及spring的处理:

第一种,构造器循环依赖:无法解决,只能抛出异常;因为在构造方法里的循环依赖,会构成一个环。比如A在创建时,发现构造器里需要B,那么此时会去创建B,B创建时发现构造器需要C,同理,C创建要A,构成一个环,死局;

第二种,setter循环依赖:通过spring容器提前暴露只完成了构造器单未完成其他注入的bean来完成,并且仅限于单例模式;

这个提前暴露的bean,其实就是一个ObjectFactory;

第三种,prototype模式下的依赖处理:处理不了;

3.5 创建Bean

前面说到真正做事的方法往往以do开头,那么doCreateBean就是做事的了,如下为经过简化后的doCreateBean源码:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
       ~~~~~~~~
        if (mbd.isSingleton()) {  //若为单例,先清除缓存中key为beanName的bean
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) { //如果缓存中没有,则实例化
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

       ~~~~~~~~
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); //bean合并后的处理,Autowired在此实现类型的预解析;
                } ~~~~~~~~~

             ~~~~~~~
		//是否单例&&是否需要提前曝光&&当前bean是否在创建
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
       ~~~~~~~~~~
       //循环依赖处理
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try { 		
        	//属性填充
            this.populateBean(beanName, mbd, instanceWrapper);
            
            //初始化bean
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } ~~~
~~~~~~~~~~~~~~~
		//循环依赖检查
        if (earlySingletonExposure) {
            ~~~~~~~~~~~~~
        }
		
        try {
      		  //注册配置了destroy-method的bean
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            
			//将已经经过一系列处理的bean返回
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

3.5.1 创建bean的实例

创建bean的第一步,从如下方法开始:

 if (instanceWrapper == null) { //如果缓存中没有,则实例化
     instanceWrapper = this.createBeanInstance(beanName, mbd, args);
 }

进入createBeanInstance方法看看:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        ~~~~~~~~~~~~~~
			
           if (resolved) {
             //根据构造函数自动注入进行构造,或者使用无参构造方法构造
                 return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
             } else {
                 Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                 return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args) ? 
                   //根据构造函数自动注入进行构造,或者使用无参构造方法构造
                   this.instantiateBean(beanName, mbd) : this.autowireConstructor(beanName, mbd, ctors, args);
             }
         }
     }
 }

这里说一下,一个bean对应的类中可能会有多个构造函数,且参数不同,spring会判断到底使用哪一个构造函数进行构造。

autowireConstructor就是根据有参的构造函数进行构造;instantiateBean是调用无参构造进行构造的。

3.5.2 属性注入populateBean

		if (bw == null) {
          ~~~~~~~~~~~·
                    if (mbd.getResolvedAutowireMode() == 1) {
                        this.autowireByName(beanName, mbd, bw, newPvs);
                    }

                    if (mbd.getResolvedAutowireMode() == 2) {
                        this.autowireByType(beanName, mbd, bw, newPvs);
                    }

                  ~~~~~~~~~~~~~~~

                if (pvs != null) {
                    this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
                }

            }
        }

值得注意的点,就是上面所示的三点,分别为:

1 autowireByName 根据名称自动注入;
2 autowireByType 根据类型自动注入;
3 applyPropertyValues 将属性应用到bean中;

感觉只要前两步就可以了,为什么会有第三步呢?

因为在自动注入时,会把需要的依赖放入PropertyValues中,而applyPropertyValues的作用则是真正把这些依赖注入已经实例化的bean中。

3.5.3 初始化bean—>initializeBean

这个方法代码不长,直接上原汁原味的源码:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

依然总结一下主要流程:

1 invokeAwareMethods: 激活Aware方法;
2 applyBeanPostProcessorsBeforeInitialization:后置处理器的使用;
3 初始化bean;
4 applyBeanPostProcessorsAfterInitialization:后置处理器的使用;

首先,这里介绍一下什么是Aware方法。

spring提供了一些Aware相关接口,常见的接口如BeanFactoryAware、ApplicationContextAware等,一个bean如果实现了这些接口,根据所实现的接口,就可以获得相应的资源。比如ApplicationContextAware接口,实现了该接口的bean,可以被注入ApplicationContext的实例,即拿到spring容器。

跟进invokeAwareMethods,如下所示,就是判断bean是否实现了部分Aware接口:

private void invokeAwareMethods(String beanName, Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware)bean).setBeanName(beanName);
            }

            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = this.getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
                }
            }

            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware)bean).setBeanFactory(this);
            }
        }

    }

后置处理器的使用,即对于BeanPostProcessor的实现,从而实现 applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization方法,在bean初始化前后进行增强;

3.5.4 返回创建好的bean

 try {
	 //注册配置了destroy-method的bean
     this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
     
	//将已经经过一系列处理的bean返回
     return exposedObject;
     }

4 打完收工

好了,到这里,bean的加载也就告一段落。基本上spring加载bean的骨架已经介绍完毕,虽然不是所有细节都面面俱到,但是对于初学源码的同学应该信息量足够了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值