Bootstrap

spring启动过程的追踪(七)——@Autowired注解生效时机、spring创建对象doGetBean方法详细解析、spring三级缓存解决循环依赖

spring创建Bean得过程非常复杂,本文将分段进行解析,尽量阐述更加清晰

1、finishBeanFactoryInitialization(beanFactory);

spring创建得单实例对象,大部分是在这个方法里面进行创建的
在这里插入图片描述
根据最后一行代码可知,其作用是实例化所有的非懒加载的单例对象

2、循环遍历beanDefinitionNames

public void preInstantiateSingletons() throws BeansException {

		List<String> beanNames;
		synchronized (this.beanDefinitionMap) {

			beanNames = new ArrayList<String>(this.beanDefinitionNames);
		}
		//beanDefinitionNames就是之前文章中加载beanDefinitions时期就把所有符合的定义信息放入了beanFactory
		
		for (String beanName : beanNames) {
			//从本地缓存获取bean的定义信息,如果没有就从beanDefinitionMap中取,beanDefinitionMap之前文章有说过
			
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
				//工厂bean的创建逻辑
				...
				}else {
				//非工厂bean的创建逻辑
					getBean(beanName);
				}
			}
		}
	}

在这里插入图片描述

2.1、getMergedBeanDefinition

获取合并的bean的定义信息,该方法在AbstractBeanFactory中,主要作用就是将bean的定义信息放入本地缓存中
在这里插入图片描述

2.2、getBean(beanName);根据bean的name获取bean对象实例

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

进入doGetBean方法,本文将doGetBean方法分段就行讲解

第一部分:getSingleton(beanName)

在这里插入图片描述

根据名称获取对象,主要就是想从缓存中获取对象,进入代码

	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) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}

singletonObjects是一个map,并且是spring用于解决依赖注入的一级缓存,前期的一些后置处理器已经创建完毕,在这个一级缓存中已经存在了对象信息
在这里插入图片描述
getSingleton如果返回了对象,则进行判断是不是工厂bean类型,如果不是直接返回对象,如果是工厂类型的则使用工厂bean方式获取对象

第二部分:getSingleton(String beanName, ObjectFactory<?> singletonFactory)

图1

在这里插入图片描述
此时将进行第一次单实例对象的创建,我们看到用到了工厂bean的形式
图2
在这里插入图片描述

接图2尾巴
在这里插入图片描述

回调getObject时进入createBean流程(见图1),继续调用 Object beanInstance = doCreateBean(beanName, mbd, args);执行完createBeanInstance方法后,对象创建完成
图3
在这里插入图片描述
对象创建后开始应用后置处理器(准确说是应用MergedBeanDefinitionPostProcessor类型的后置处理器)
图4
在这里插入图片描述
图5
在这里插入图片描述
关注AutowiredAnnotationBeanPostProcessor后置处理器,主要处理@Autowired注解的

图6
111
找到了当前对象的一个被@Autowired注解标注的属性
图7
在这里插入图片描述

doCreateBean方法继续向下走
图8
在这里插入图片描述

doCreateBean方法继续向下走
图9
在这里插入图片描述
进入populateBean属性封装方法,再一次进行后置处理器操作(准确的说是InstantiationAwareBeanPostProcessor类型的后置处理器)
图10
001
重点关注AutowiredWiredAnnotationBeanPostProcessor
图11
在这里插入图片描述
重点:再一次调用了这个后置处理器,之前已经调用过一次,所以这次findAutowiringMetadata这个方法获取元数据会走缓存
图12
在这里插入图片描述
构建元数据的方法也很简单,通过反射获取属性
图13
在这里插入图片描述
回到AutowiredWiredAnnotationBeanPostProcessor的方法调用(见图11)
此时调用metadata.inject元数据注入,
在这里插入图片描述
进入element.inject

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

进入findAutowireCandidates方法
重点关注两个方法,图中标注
在这里插入图片描述
进入方法1:

图14

在这里插入图片描述

图15
在这里插入图片描述

遍历循环所有的bean定义信息名称数组,找到匹配当前对象属性类型的bean名称
在这里插入图片描述
获取bean的定义信息和之前一样,都是系统中已经存在的bean的定义信息
继续看上图的doGetBeanNamesForType方法,会把符合类型的bean的name放入result返回到图15最后到图14

在这里插入图片描述

进入方法2(图14上面)
此时要给当前对象的属性进行创建对象,创建完成后进入当前对象的属性赋值方法,回到图9,给当前对象设置属性信息
在这里插入图片描述
属性赋值完成后进行initializeBean初始化对象,初始化前后会又有处理器进行工作,其中初始化方法需要实现当前类实现InitializingBean接口才会有哦

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
	   ...
		}
		else {
		   //调用aware类型的后置处理器
		   
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
		   //调用后置处理器的beforeInit...方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
		   //调用对象的init方法
			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()) {
	    	//调用对象的afterInit...方法
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

在这里插入图片描述

总结

文章可能比较长,但是如果能一点点跟进,会对自己认识spring创建对象有很大的帮助,最后对于spring循环依赖,简单的说下,其实如果一点点跟进,会发现spring三级缓存处理循环依赖特别清晰,三级缓存就是三个map,对象刚开始创建的时候会先放到singletonFactories这个map,如果对象A有属性B,会在属性封装前创建属性B对象也放入了singletonFactories这个map,当这个属性B对象又依赖了这个对象A时,B在属性封装时会去getBean创建A,此时 看如下代码,对象A会被放入了earlySingletonObjects这个map,并且从singletonFactories去除,对象在最终创建完成后会进行addSingleton操作(见接图2尾巴),放入singletonObjects这个map

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) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}
;