Spring源码解读之IOC容器

本节介绍神秘的IOC容器,探究IOC是怎样工作的?Bean创建的时机是怎样的?以及Spring是如何解决循环bean依赖的?当了解这些之后,遇到Spring报的一些错就不会无里头了。俗话说一图胜似千言万语,先上图, 依据自己对源码的分析和了解大概将IOC的知识点分为这几块。

                                 <0>IOC容器涉及知识点

在进入正文之前大概先对以上六点做一个整体介绍,认识一下它们是怎么回事。

1、Bean生命周期Bean的实例化-->Bean的初始化(初始化方法、属性赋值)-->Bean的使用-->bean销毁。

注:标注红色五角星是bean实例化流程中最重要的三部分,将会在getBean()流程中详细讲解。

                                                                      <1>Bean的实例化流程图

2、循环依赖:

  • 构造器循环依赖 ---- 无解,将抛出BeanCurrentlyInCreationException异常表示循环依赖
  • field属性的循环依赖
    • setter循环依赖 ---- spring可以通过提前曝光进行解决)
    • prototype作用域bean的循环依赖 ---- 因为不做缓存所以无解

Spring怎么解决循环依赖?

        ①singletonFactories 、earlySingletonObjects、singletonObjects三级缓存。

        ②创建Bean的时候会提前曝光,在属性赋值的时候,会先将通过构造器创建出来的(还没初始化,属性值还都是null)bean给暴露出来,给属性引用。

3、常用扩展点(前置后置增强):

InstantiationAwareBeanPostProcessor:   实例化前后 
    postProcessBeforeInstantiation()
    postProcessAfterInstantiation()

BeanPostProcessor:  初始化前后
    postProcessBeforeInitialization()
    postProcessAfterInitialization()
区别:Instantiation表示实例化,Initialization表示初始化。实例化的意思在对象还未生成,初始化的意思在对象已经生成。

InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置;BeanPostProcessor接口允许在调用初始化方法前后对Bean进行额外的处理。Bean后置处理器对IOC容器里的所有Bean实例逐一处理,而非单一实例。其典型应用是:检查Bean属性的正确性或根据特定的标准更改Bean的属性。

4、BeanFactory和ApplicationContext前世今生:

spring的两种容器:a、BeanFactoy
                               b、ApplicationContext应用上下文   

 ApplicationContext和BeanFactory都是用于加载 bean 的,但是ApplicationContext提供了更多的功能,包含了BeanFactory的所有功能。

BeanFactory:BeanhFactory使用延迟加载所有的Bean,为了从BeanhFactory得到一个Bean,只要调用getBean()方法,就能获得Bean。

ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:

      a. 国际化支持
      b. 资源访问:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”
      c. 事件传递:通过实现ApplicationContextAware接口

5、无所不知的Aware:

Aware是一个具有标识作用的超级接口,实现该接口的bean是具有被spring 容器通知的能力的,而被通知的方式就是通过回调。也就是说:直接或间接实现了这个接口的类,都具有被spring容器通知的能力。

《1、Bean生命周期》中的介绍的第3步检查Aware接口并设置相关依赖 ----- invokeAwareMethods(),则是通过回调设置beanName。例如实现了BeanNameAware则具备获取获得到容器中Bean的名称的能力。

6、Context的初始化过程:

    context的出初始化依旧离不开接口ApplicationContext;AbstractApplicationContext是它的抽象基础类,无论是XML文件配置的还是基于注解配置的Bean,其最终都是真正从下图开始,只不过是前期BeanDefinition的处理不同而已。

                                                              <2>Context的初始化主要步骤图


正文:

IOC容器:IOC全程为Inversion of Control,即控制反转,就是由 Spring IOC 容器来负责对象的生命周期和对象之间的关系。白话不多说仅此一句就够了。下面来自让我们真正进入spring内部,了解IOC的思想以及技术点。

目录

目录

一、前期认识:

二、Bean 的生命周期:

三、循环依赖:

四、常用扩展点(前置后置增强):

五、BeanFactory和ApplicationContext前世今生:

六、无所不知的Aware:

七、Context的初始化过程:



一、前期认识:

刚开始我们先介绍下关键的几个类以及它们各自扮演的角色和关系。

  • DefaultListableBeanFactory :: preInstantiateSingletons()----->getBean()context初始化时获取bean入口

        DefaultListableBeanFactory是整个bean加载的核心部分,是Spring注册及加载bean的默认实现(即所有的BeanDefinition就是注册在此类的map中),它是一个基于bean定义对象的成熟bean工厂,典型的用法是在访问beans之前(即项目启动的时候)注册所有的Bean;

        而XmlBeanFactory对DefaultListableBeanFactory类进行了扩展,主要用于从XML文档中读取BeanDefinition,对于注册及获取Bean都是使用从父类DefaultListableBeanFactory继承的方法去实现,而唯独与父类不同的个性化实现就是增加了XmlBeanDefinitionReader类型的reader属性。

  • AbstractBeanFactory :: doGetBean()真正获取bean的方法

         AbstractBeanFactory 继承DefaultSingletonBeanRegistry并实现了ConfigurableBeanFactory,因此该类具有管理、注册、缓存单例bean能力,并且增加了对FactoryBean的特殊处理功能。

  • DefaultSingletonBeanRegistry :: getSingleton()获取单例bean

        它继承SimpleAliasRegistry类和实现了SingletonBeanRegistry接口,因此这个类可以有别名注册的功能和单例bean注册的功能(缓存单例bean--map),并且还支持注册DisposableBean实例;它依赖ObjectFactory接口和DisposableBean接口(关闭注册表时调用到了destroy方法)。

  • AbstractAutowireCapableBeanFactory :: doCreateBean()创建bean实例

        综合AbstractBeanFactory并对接口AutowireCapableBeanFactory进行实现。供bean的创建 (有construct方法), 属性注值, 绑定 (包括自动绑定)和初始化。处理运行时bean引用, 解析管理的集合, 调用初始化方法。提供通过属性name、属性type以及构造器的注入

                                                                            图<1-1>创建bean关键类图

二、Bean 的生命周期:

1、bean的作用域:

singleton(缺省作用域)在整个应用中,只创建bean的一个实例,在IOC容器中共享,容器创建的时候就实例化了这个bean
prototype

每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例,相当于每次都new bean(),容器创建的时候没有实例化了bean,而是在请求获取的时候才会创建对象

request

每次http请求都会创建一个bean实例,这个bean实例只在当前request请求内有效,请求结束的时候,这个bean实例被销毁;该作用域仅适用于WebApplicationContext环境

session同一个http session共享一个bean实例,不同的Session使用不同的Bean,该作用域仅适用于WebApplicationContext环境
globalSession一般用于Prolet应用环境,该作用域仅适用于WebApplicationContext环境

2、生命周期从Bean实例化开始

     概述的图<1>中便是Bean实例化的大致流程图,实例化所涉及的关键类的类图如图<1-1>注意黄色注释的四个类:

  • DefaultListableBeanFactory :: preInstantiateSingletons()----->getBean()获取bean的地方
  • AbstractBeanFactory :: doGetBean()真正获取bean的方法
  • DefaultSingletonBeanRegistry :: getSingleton()获取单例bean
  • AbstractAutowireCapableBeanFactory :: doCreateBean()创建bean实例

在深入源码之前综合概述中的流程图,先宏观分析对源码做个大概的了解:

                                                    图<2-1>bean实例化流程分析

读过这个图,大家可能对第二步-->第三步有点疑问,ObjectFactory接口类的getObject()为什么会直接调用createBean(...)方法,其实ObjectFactory是一个函数式接口,调用getObject()时,其实真正回去回调getSIngleton(...)参数中的函数表达式()->createBean(...)。

通过宏观分析,让我们对Bean的实例化过程有一个大概的思路,下面开始深入源码一步步解读:

首先在正式分析createBean(String, RootBeanDefinition, Object[])方法前,我们先来看看 createBean 方法是在哪里被调用的(如下图代码)。doGetBean 方法的代码片段,从中可以发现 createBean 方法被匿名工厂类ObjectFactory的 getObject 方法包裹,但这个匿名工厂类对象并未直接调用 getObject 方法。而是将自身作为参数传给了getSingleton(String, ObjectFactory)方法,createBean ()真正是在getSingleton()方法中回调的。

AbstractBeanFactory:: 
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		// ...省略...
        /********* 1、先从缓存中取 **********/
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			// ...省略...
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
       /********* 2、缓存中中没有就创建 **********/
		else {
			
           /********* 2.1、 如果是原型bean并且正在被创建,则报异常(循环依赖会在第三部分介绍)**********/
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
		
            /********* 2.2、标记正在被创建 **********/
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

            /********* 2.2、单例bean开始创建**********/
			// Create bean instance.
			if (mbd.isSingleton()) {
                  /********* 2.3、开始获取单例bean*********/
				sharedInstance = getSingleton(beanName, () -> {
					try {
                /********* 2.4 createBean 方法被匿名工厂类的 getObject 方法包裹,
                       但这个匿名工厂类对象并未直接调用 getObject方法,而是将自
                      身作为参数传给了2.3步的getSingleton(String, ObjectFactory)
                      方法*********/
					  return createBean(beanName, mbd, args);
					}
					catch (BeansException ex) {
					
				          destroySingleton(beanName);
				          throw ex;
				    }
			   });
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
		}
	}		
		
	return (T) bean;
}

doGetBean 方法的大概处理步骤如下(代码中有每一步相关注释):

    1. 先从缓存中取,取缓存顺序依次是singletonObjects-->earlySingletonObjects-->singletonFactories,取到就直接返回。
    2. 若为空,如果是原型bean并且正在被创建,则报异常
    3. 若是单例bean,则标记正在被创建
    4. 开始创建单例Bean,createBean 方法被匿名工厂类的 getObject 方法包裹,但这个匿名工厂类对象并未直接调用
getObject 方法,而是在getSingleton(String, ObjectFactory)方法中回调。

代码中注释的2.1也解释了prototype作用域bean的循环依赖Spring是无助的。

从上面代码分析createBean()是在getSingleton(String, ObjectFactory)方法中回调的,我们来具体分析下此方法是如何处理的。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "'beanName' must not be null");
    synchronized (this.singletonObjects) {
        // 1、从缓存中获取单例 bean,若不为空,则直接返回,不用再创建
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // ....省略....
            /* 
             * 2、将 beanName 添加到 singletonsCurrentlyInCreation 集合中,
             * 用于表明 beanName 对应的 bean 正在创建中(表明单例bean正在创建中)
             */
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<Exception>();
            }
            try {
                /*****3、通过 getObject 方法调用 createBean 方法创建 bean 实例***/
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                 // ....省略....
            }
            catch (BeanCreationException ex) {
                 // ....省略....
            }
            finally {
               
                /***4、 将 beanName 从 singletonsCurrentlyInCreation 移除***/
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                /* 
                 * 5、将 <beanName, singletonObject> 键值对添加到 singletonObjects 集合中,
                 * 并从其他集合(比如 earlySingletonObjects)中移除 singletonObject 记录
                 */
                addSingleton(beanName, singletonObject);
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

getSingleton(String, ObjectFactory)只看关键代码其逻辑不是很复杂,大概处理逻辑如下(代码中每一步也有相关注释):

  1. 先从 singletonObjects 集合获取 bean 实例,若不为空,则直接返回
  2. 若为空,进入创建 bean 实例阶段。先将 beanName 添加到 singletonsCurrentlyInCreation
  3. 通过 getObject 方法回调getSingleton(String, ObjectFactory)的入参 createBean() 方法创建 bean 实例
  4. 无论是否创建成功最终都会将 beanName 从 singletonsCurrentlyInCreation 集合中移除
  5. 将 <beanName, singletonObject> 映射缓存到 singletonObjects (缓存所有的单实例bean)集合中

从上面的分析中,我们知道了 createBean 方法在何处被调用的。那么接下来我们一起重点深入 createBean 方法的源码中,来看看这个方法具体都做了什么事情。

AbstractAutowireCapableBeanFactory::
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		
		RootBeanDefinition mbdToUse = mbd;

		// ... 省略...

		try {
			/**** 1、Give BeanPostProcessors a chance to return a proxy instead of the 
              *** target bean instance.(实例化前后置处理,如果不为空则直接返回,一般bean创建 
              *** 都为空)
              *** 问题:为什么spring是在初始化之后proxy而不是resolveBeforeInstantiation
              *** resolveBeforeInstantiation只是针对有自定义的targetsource,因为自定义的
              *** targetsource不是spring的bean那么肯定不需要进行后续的一系列的实例化 初始化。所以
              ***  可以在resolveBeforeInstantiation直接进行proxy
              ***/
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
            /****2、开始真正创建bean******/
			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);
		}
	}

createBean 方法处理较为简单,主要是有一个预处理-----后置处理器处理(代码中的第1步),当然对于一般的bean处理结果都返回空;然后真正创建bean的逻辑是在doCreateBean()方法中;这个doxxx()是Spring框架中经常用的,往往在做某件事情之前都会做一些预备工作,最终的处理逻辑在doxxx()方法中。

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

		/* 
         * BeanWrapper 是一个基础接口,由接口名可看出这个接口的实现类用于包裹 bean 实例。
         * 通过 BeanWrapper 的实现类可以方便的设置/获取 bean 实例的属性
         */
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}

        /* 
         * 1.反射创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。 
         * createBeanInstance 中包含三种创建 bean 实例的方式:
         *   ①. 通过工厂方法创建 bean 实例
         *   ②. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例
         *   ③. 通过无参构造方法方法创建 bean 实例
         *
         *   注意:若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用  
         *   CGLIB增强 bean 实例。(可以先不关注,只关注主流程创建bean实例)
         */
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}

        /*** 补充:此处创建的bean是一个原始的bean,并没有任何属性填充和初始化。**/
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// ...省略...

    /*
     * 2、(解决循环依赖)earlySingletonExposure 是一个重要的变量,这里要说明一下。该变量用于表
     * 示是否提前暴露单例 bean,用于解决循环依赖。切记:此处的bean是原始bean,并没有属性赋值和初
     * 始化,因为是引用,所以bean初始化完成之后就会变成完整的bean。 
     * earlySingletonExposure 由三个条件综合而成,如下:
     *   条件1:mbd.isSingleton() - 表示 bean 是否是单例类型
     *   条件2:allowCircularReferences - 是否允许循环依赖
     *   条件3:isSingletonCurrentlyInCreation(beanName) - 当前 bean 是否处于创建的状态中
     * 
     * earlySingletonExposure = 条件1 && 条件2 && 条件3 
     *                        = 单例 && 是否允许循环依赖 && 是否存于创建状态中。
     */
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
             /** 补充:获取获取原始对象早期 bean 的引用,如果 bean 中的方法被 AOP 切点所匹配 
              ** 到,在 getEarlyBeanReference 方法中,会执行 AOP 相关逻辑。 
              ** 若 bean 未被 AOP 拦截,getEarlyBeanReference 原样返回 
              ** bean,所以大家可以把
              **      return getEarlyBeanReference(beanName, mbd, bean) 
              ** 等价于:
              **      return bean;
              **/
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
              /*** 3、属性赋值,稍后专门分析***/
			populateBean(beanName, mbd, instanceWrapper);
            /*
             * 4、进行余下的初始化工作,详细如下:
             *   ①. 判断 bean 是否实现了 BeanNameAware、BeanFactoryAware、
             *    BeanClassLoaderAware 等接口,并执行接口方法
             *   ②. 应用 bean 初始化前置操作
             *   ③. 如果 bean 实现了 InitializingBean 接口,则执行 afterPropertiesSet 
             *      方法。如果用户配置了 init-method,则调用相关方法执行自定义初始化逻辑
             *   ④. 应用 bean 初始化后置操作
             * 
             * 另外,AOP 相关逻辑也会在该方法中织入切面逻辑,此时的 exposedObject 就变成了
             * 一个代理对象了
             */
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			
		}

		// ...省略...

		// Register bean as disposable.
		try {
        /**** 5、注册销毁逻辑***/
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			
		}

		return exposedObject;
	}

三、循环依赖:

依据第二节的Bean实例化步骤分析,我们来做一个简单的流程分析:
       1. 创建原始 bean 实例 → createBeanInstance(beanName, mbd, args)
       2. 添加原始对象工厂对象到 singletonFactories 缓存中 → addSingletonFactory(beanName, () ->  getEarlyBeanReference(beanName, mbd, bean));                 
       3. 填充属性,解析依赖 → populateBean(beanName, mbd, instanceWrapper)

重点来了,addSingletonFactory()就是解决循环依赖的关键点,因为此方法可以将原始对象的引用提早加入缓存以进行曝光。举个例子,假设 ClassA和ClassB相互依赖,那么实例化ClassA时通过方法addSingletonFactory()先将自己的原始Bean加入缓存提前暴露引用,然后在调用populateBean()进行属性填充时,发现依赖ClassB,然后就会首先实例化ClassB;ClassB当遇到这个方法时也会解析自己的依赖,然后对于ClassA这个依赖,会在getSington(String beanName)时获取到早期暴露的原始bean,获取到依赖的早期bean之后,ClassB就可以完成实例化工作,然后ClassA就可以获取到完整的ClassB实例,最后再会退回来继续实例化ClassA,当Class完成实例化之后ClassA和ClassB之间就完成了完整的bean依赖也处于可用状态。

getSington(String beanName)具体源码如下,源码中提到了获取bean时的几个缓存,同时在概述的第2节我们也提到了这几个缓存,下面详细介绍下这几个缓存:

缓存容器作用
singletonObjectsMap(key=beanName,value=bean实例)用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
earlySingletonObjectsMap存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
singletonFactoriesMap存放 bean 工厂对象,用于解决循环依赖

        getSington(String beanName)是在doGetBean()方法中调用的(可以看上一节创建bean实例源码分析),从代码中分析逻辑很简单:
1. 首先从 singletonObjects 缓存中获取 bean 实例。
2. 若未命中,再去 earlySingletonObjects 缓存中获取原始 bean 实例。
3. 如果仍未命中,则从 singletonFactory 缓存中获取 ObjectFactory 对象,然后再调用 getObject 方法获取原始 bean 实例的应用,也就是早期引用。
4. 获取成功后,将该实例放入 earlySingletonObjects 缓存中,并将 ObjectFactory 对象从 singletonFactories 移除。

DefaultSingletonBeanRegistry::
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}


	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		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) {
                        /**** 从缓存中拿到早期原始bean *****/
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

最后一张图来结束这一小节:

四、常用扩展点(前置后置增强):

依旧是先上图让我们对bean的增强器的作用点有大概的宏观了解,如下图所示,其实简单理解就是:

bean实例化前后分别会由InstantiationAwareBeanPostProcessor的前置和后置处理方法去处理,而在初始化前后会由BeanPostProcessor的前置和后置处理方法处理。

注意区别:InstantiationAwareBeanPostProcessor的两个方法是由Instantiation结尾,表明是实例化专用;BeanPostProcessor的两个方法是由Initialization结尾表明是初始化专用。

 

                                                                        图<4-1>处理器在bean创建流程中的插入点

下面根据上图以及源码来详细分析,有部分源码可能和前面有重复,所以只关注本节要讲述的源码,

1、InstantiationAwareBeanPostProcessor前置代码分析:

AbstractAutowireCapableBeanFactory::

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

	    // ...省略...
		try {
             /**** 1、Give BeanPostProcessors a chance to return a proxy instead of the 
              *** target bean instance.(实例化前后置处理,如果不为空则直接返回,一般bean创建 
              *** 都为空)
              *** 继续跟进方法内部分析
              ***/
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			
		}

		try {
            /** 2、前置处理结束,开始创建bean **/
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			
		}
		catch (Throwable ex) {
			
		}
	}

---------------------------------------------------------------------------------
AbstractAutowireCapableBeanFactory::

/** 在 resolveBeforeInstantiation 方法中,当前置处理方法返回的 bean 不为空时,后置处理才会被执
 * 行。前置处理器是 InstantiationAwareBeanPostProcessor 类型的,该种类型的处理器一般用在 Spring
 * 框架内。
 *** 问题:为什么spring是在初始化之后proxy而不是resolveBeforeInstantiation
 *** resolveBeforeInstantiation只是针对有自定义的targetsource,因为自定义的
 *** targetsource不是spring的bean那么肯定不需要进行后续的一系列的实例化 初始化。所以
 ***  可以在resolveBeforeInstantiation直接进行proxy
 **/
	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
                    /* 
                     * 一般单例bean在这边处理都是返回null,这边不是重点,一般bean的创建这边都会返
                     * 回null
                     */
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
---------------------------------------------------------------------------------------

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        /** 1、只针对接口是InstantiationAwareBeanPostProcessor 类型的**/
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            /* 2、bean 初始化前置处理。如果返回null;后面的所有 
             * 后置处理器的方法就不执行,直接返回(所以执行顺序很重要)
             */
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

总结:真正创建bean之前会给处理器一个机会看是否要给目标bean生成动态代理对象,这儿的机会主要是针对AOP的,普通的Bean创建都会返回null,然后开始按正常创建Bean的逻辑去执行doCreateBean()方法。

2、InstantiationAwareBeanPostProcessor后置代码分析:

 实例化后置处理这部分代码主要在populateBean()方法中,这在图<4-1>中有体现

AbstractAutowireCapableBeanFactory::

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		
     /*
     * 1、又是给一个机会
     * 在属性被填充前,给 InstantiationAwareBeanPostProcessor 类型的后置处理器一个修改 
     * bean 状态的机会。关于这段后置引用,官方的解释是:让用户可以自定义属性注入。比如用户实现一
     * 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过 
     * postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。当然,如果无
     * 特殊需求,直接使用配置中的信息注入即可。另外,Spring 并不建议大家直接实现 
     * InstantiationAwareBeanPostProcessor 接口,如果想实现这种类型的后置处理器,更建议
     * 通过继承 InstantiationAwareBeanPostProcessorAdapter 抽象类实现自定义后置处理器。
     */
  
		/** Give any InstantiationAwareBeanPostProcessors the opportunity to modify 
		 ** the state of the bean before properties are set. This can be used, for 
		 ** example, to support styles of field injection.
              **/
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		/... 省略....

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

总结:这个postProcessAfterInstantiation返回值要注意,因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返true,postProcessPropertyValues就会被执行。

3、BeanPostProcessor的前置、后置分析源码:

在图<4-1>中有体现,处理器插入点其实是在init-method方法生效前后调用postProcessBeforeInitialization和postProcessAfterInitialization方法

AbstractAutowireCapableBeanFactory::

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		// ...省略...

		Object wrappedBean = bean;

		if (mbd == null || !mbd.isSynthetic()) {
      /** 1、执行 bean 初始化前置操作**/
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
        /*
         * 2、调用初始化方法:
         * ①. 若 bean 实现了 InitializingBean 接口,则调用 afterPropertiesSet 方法
         * ②. 若用户配置了 bean 的 init-method 属性,则调用用户在配置中指定的方法
         */
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
 /**3、 执行 bean 初始化后置操作,注意AOP 就是在后置处理 postProcessAfterInitialization 方法
  ** 中向目标对象中织如切面逻辑的, AOP 模块中的AbstractAutoProxyCreator抽象类间接实现了这个接口中
  * 的postProcessBeforeInstantiation方法,AOP代理的创建就是在这个方法内部循环processors,通过
  * AbstractAutoProxyCreator创建
  * 
  **/
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

总结:通过上面源码分析在加上面流程图解应该是很清晰了:

1、实例化完成,属性赋值完成

2、执行初始化前置处理逻辑一般bean的创建会返回原bean

3、执行实现了接口的初始化方法

4、执行初始化后置处理逻辑一般bean的创建会返回原bean

五、BeanFactory和ApplicationContext前世今生:

Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类。事实上,Spring提供了两种不同的容器:一种是最基本的BeanFactory,另一种是扩展的ApplicationContext。BeanFactory 仅提供了最基本的依赖注入支持,而 ApplicationContext 则扩展了BeanFactory ,提供了更多的额外功能。二者对Bean的初始化也有很大区别。BeanFactory当需要调用时读取配置信息,生成某个类的实例。如果读入的Bean配置正确,则其他的配置中有错误也不会影响程序的运行。而ApplicationContext 在初始化时就把 xml 的配置信息读入内存,对 XML 文件进行检验,如果配置文件没有错误,就创建所有的Bean ,直接为应用程序服务。相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动将它们注册到应用上下文中;而BeanFactory需要在代码中通过手工调用addBeanPostProcessor()方法进行注册。

类图如下ApplicationContext是继承了BeanFactory,并且也继承了其它的接口,说明ApplicationContext是对BeanFactory接口的扩展,具备BeanFactory不具有的功能。

1、BeanFactory介绍:

Spring容器最基本的接口就是BeanFactory。BeanFactory负责配置、创建、管理Bean,它有一个子接口ApplicationContext也被称为Spring上下文,容器同时还管理着Bean和Bean之间的依赖关系。spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,因此可以这么说,
DefaultListableBeanFactory 是整个spring ioc的始祖

BeanFactory是Spring bean容器的根接口,提供获取bean,是否包含bean,是否单例与原型,获取bean类型,bean 别名的方法 。它最主要的方法就是getBean(String beanName),因此前面创建Bean所介绍的主要类都实现自BeanFactory接口。

BeanFactory的三个子接口:
 * HierarchicalBeanFactory:提供父容器的访问功能
 * ListableBeanFactory:提供了批量获取Bean的方法
 * AutowireCapableBeanFactory:它继承了BeanFactory接口,该接口是一个自动注入的ioc bean工厂接口,主要定义bean的创建、初始化、自动注入以及bean初始化前置、后置增强的接口;在BeanFactory基础上实现对已存在实例的管理。

2、ApplicationContext介绍:

    ApplicationContext常用实现类作用
AnnotationConfigApplicationContext从一个或多个基于java的配置类中加载上下文定义,适用于java注解的方式。
ClassPathXmlApplicationContext从类路径下的一个或多个xml配置文件中加载上下文定义,适用于xml配置的方式。
FileSystemXmlApplicationContext从文件系统下的一个或多个xml配置文件中加载上下文定义,也就是说系统盘符中加载xml配置文件。
AnnotationConfigWebApplicationContext专门为web应用准备的,适用于注解方式。
XmlWebApplicationContext从web应用下的一个或多个xml配置文件加载上下文定义,适用于xml配置方式。
  

由于ApplicationContext会预先初始化所有的Singleton Bean,于是在系统创建前期会有较大的系统开销,但一旦ApplicationContext初始化完成,程序后面获取Singleton Bean实例时候将有较好的性能。也可以为bean设置lazy-init属性为true,即Spring容器将不会预先初始化该bean。

六、无所不知的Aware:

spring Aware 的目的是为了让bean获取spring容器的服务,Aware接口如上图所示。

我们只介绍常用的这三个接口:

  • BeanNameAware :可以获取容器中bean的名称
  • BeanFactoryAware:获取当前bean factory这也可以调用容器的服务
  • ApplicationContextAware: 当前的applicationContext, 这也可以调用容器的服务

还记得概述中 图<1>Bean的实例化流程图吗,属性赋值的下一步就是Aware接口检查,我们来分析下源码:
在属性赋值之后,bean初始化之前会有一个检查设置Aware的机会,以便为bean提供Spring的一些资源。在invokeAwareMethods()方法中只检测了上面三个Aware接口,那么问题来了其他的Aware接口怎么设值,例如开发中经常自定义实现了ApplicationContextAware用来获取应用上下文,它的setApplicationContext()方法是在哪里被调用的呢?
答:如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中-------此处的调用设置其实是在处理器ApplicationContextAwareProcessor中做的,ApplicationContextAwareProcessor实现了BeanPostProcessor接口。

 


AbstractAutowireCapableBeanFactory::

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
      
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
            /** 1、检查Aware接口并进行设置,重点介绍此方法 **/
			invokeAwareMethods(beanName, bean);
		}

        /** 2、很熟悉了,就是初始化前后增强,前面已经介绍不再多说**/
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

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

		return wrappedBean;
	}
=============================================================================================
/**
如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;
如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;
**/

	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

七、Context的初始化过程:

Context的初始化过程在概述中<6、Context的初始化过程>已做简单叙述,大致过程如概述中的第6小节的图<2>所示,具体每一步我们来看源码:

AnnotationConfigApplicationContext::

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
//准备上下文的刷新,
            prepareRefresh();
            // Tell the subclass to refresh the internal bean factory.
//得到新的Bean工厂,应用上下文加载bean就是在这里面实现的
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//准备bean工厂用在上下文中
            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);
            try {
                // Allows post-processing of the bean factory in context subclasses.
//允许子类上下问处理bean工厂
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
//请求工厂处理器作为beans注册在上下文
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
//注册bean处理器拦截bean创建
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
//初始化上下文中消息源
                initMessageSource();
                // Initialize event multicaster for this context.
//初始化上下文中事件广播
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
//初始化其他具体bean
                onRefresh();
                // Check for listener beans and register them.
//检查监听bean并注册
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
//实例化未初始化单例
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
//最后一步发布相应事件
                finishRefresh();
            }

AnnotationConfigApplicationContext::
-------> AbstractApplicationContext: refresh() bean加载的入口
       -------> obtainFreshBeanFactory():获取BeanFactory(返回GenericApplicationContext创建的BeanFactory对象--DefaultListableBeanFactory)
      --------> prepareBeanFactory(beanFactory);方为了下面在Spring上下文中使用BeanFactory做准备(对刚才创建BeanFactory对象进行一些设置属性)
      --------> postProcessBeanFactory(beanFactory);BeanFactory准备工作完成后进行的后置处理工作;子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置
      --------> invokeBeanFactoryPostProcessors(beanFactory);该方法的调用必须在所有的singleton实例化之前,而且从该方法的名称可以看出来,引入了IOC的Processor角色(其实就是Bean工厂里的处理器)。

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	/** 就是将所有的BeanFactoryPostProcessor调用了一遍**/	
     PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

BeanFactoryPostProcessor:BeanFactory的后置处理器。在BeanFactory标准初始化之后执行,执行BeanFactoryPostProcessor的方法
    两个接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
    1)、执行BeanFactoryPostProcessor的方法;
        先执行BeanDefinitionRegistryPostProcessor
        1)、获取所有的BeanDefinitionRegistryPostProcessor;
        2)、看先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor、
            postProcessor.postProcessBeanDefinitionRegistry(registry)
        3)、再执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor;
            postProcessor.postProcessBeanDefinitionRegistry(registry)
        4)、最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors;
            postProcessor.postProcessBeanDefinitionRegistry(registry)
        再执行BeanFactoryPostProcessor的方法
        1)、获取所有的BeanFactoryPostProcessor
        2)、看先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor、
            postProcessor.postProcessBeanFactory()
        3)、在执行实现了Ordered顺序接口的BeanFactoryPostProcessor;
            postProcessor.postProcessBeanFactory()
        4)、最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor;
            postProcessor.postProcessBeanFactory()
--------> registerBeanPostProcessors(beanFactory): 注册BeanPostProcessor(Bean的后置处理器);不同接口类型的BeanPostProcessor,在Bean创建前后的执行时机是不一样的。【 intercept bean creation】
--------> finishBeanInitialization(beanFactory): 这个方法里面,用来初始化非懒加载的bean。并非所有bean都在容器启动的时候实例化。在xml中配置bean的时候,有个lazy-ini属性,默认为false。所以默认情况下,单例的非懒加载的bean在容器启动的时候会实例化。如果是懒加载的,那么在getBean的时候,再实例化。(前面已经具体分析过)

总结:
    1)、Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息;
        1)、xml注册bean;<bean>
        2)、注解注册Bean;@Service、@Component、@Bean、xxx
    2)、Spring容器会合适的时机创建这些Bean
        1)、用到这个bean的时候;利用getBean创建bean;创建好以后保存在容器中;
        2)、统一创建剩下所有的bean的时候;finishBeanFactoryInitialization();
    3)、后置处理器;BeanPostProcessor
        1)、每一个bean创建完成,都会使用各种后置处理器进行处理;来增强bean的功能;
            AutowiredAnnotationBeanPostProcessor:处理自动注入
            AnnotationAwareAspectJAutoProxyCreator:来做AOP功能;
            xxx....
            增强的功能注解:
            AsyncAnnotationBeanPostProcessor
            ....

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值