四,Bean的加载过程

入口:

TestBean  bean = beanFactory.getBean("testBean");

上述方法实质上是调用的doGetBean方法:

/**

getBean(beanName) ---> doGetBean(beanName,null,null,false);

*/


protected <T> T doGetBean(final String name,final Class<T> requiredType,final Object[] atgs,boolean typeCheckOnly){

	
	/*
	--------------------------------------------------------------------------------------------
	提取beanName
	---------------------------------------------------------------------------------------------
		这里的name参数不一定是我们需要的beanName,还有可能是alias、beanFactoryName(加&)
		1.如果是带&的,说明获取的是factoryBean,而不是调用其getObject方法来获取其生产的bean
		2.如果是别名alias,则需要取出最终的beanName,
		  由于map中肯定不存在循环别名依赖,a-b,b->bean类似最终获取beanName的方式应该类似下述代码:
		  while(map.keySet().contain(key)){
			String beanName = map.get(key);
			key = beanName;
		  }
		  return beanName;
	*/
	final String beanName = transformedBeanName(name);
	Object bean;
	//尝试从单例缓存中加载bean
	//第3小结讲述
	Object sharedInstance = getSingleton(beanName);
	if(sharedInstance != null && args !=null){
		//其中有些不太重要的代码没写
		if(isSingletonCurrentlyInCreation(beanName)){
			//只是记录相关日志
			System.out.print("返回一个正在创建的bean");
		}else{
			System.out.print("返回单例缓存中的bean");
		}
		//第二小结讲述
		//获取最终的bean状态结构
		bean = getObjectForBeanInstance(sharedInstance,name,beanName,null);
	}else{
		/*
			判断当前创建的bean是否是单例
			因为只有单例的bean才会去解决循环依赖1
		*/
		if(isPrototypeCurrentlyInCreationException(beanName)){
			抛出异常
		}
	
	]
}

1.尝试从单例缓存中加载bean

入口方法:

//上一级方法getSingleton(beanName)直接调用了getSingleton(beanName,true)
protected Object getSingleton(String beanName,boolean allowEarlyReference){
	//首先尝试从singletonObjets里面获取bean的实例
	Object SingletonObject = this.singletonObjects.get(beanName);
	if(SingletonObject == null){
		synchronized(this.singletonObjects){
			//从singletonObjets获取不到
			//再次尝试从earlySingletonObjects里面获取实例
			//--->因为还未加载此bean的时候由于先前有的bean属性里面有此bean,所以可能在之前就被加载了
			singletonObject = this.earlySingletonObjects.get(beanName);
			if(singletonObject  == null  && allowEarlyReference){
				//尝试获取创建该bean的ObjectFactory
				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);
}

下面对几个缓存bean的map进行以下说明:

singletonObjects:用于保存beanName和bean实例之间的关系

singletonFactories:用于保存beanName和创建bean的工厂ObjectFactory之间的关系

earlySingletonObjects:保存beanName和bean实例之间的关系,但是不同的是这个map可以在bean还未创建完成就可以获取到bean了,用于循环检测

registeredSingletons:保存当前所有已经注册的bean

2.从bean的实例中获取对象

如果在上一步中获取了bean,但是这个bean是最初始的状态,有可能不是我们需要的最终的bean

其实就是需要检测一下这个bean是不是FactoryBean,如果是,我们还需要调用其getObject方法来获取我们最终想要的bean

而getObjectForBeanInstance方法正是完成这个任务的

//这里的name是最开始beanFactory.get()使用的name,而beanName是解析出来的唯一标识
protected Object getObjectForBeanInstance(String name,String beanName,Object beanInstance,RootBeanDefinition rbd){
	
	if(如果指定的name是&开头的而且beanInstance又不是FactoryBean类型){
		//说明用户需要获取FactoryBean,但是该bean未实现FactoryBean接口
		抛出异常
	}
	
	/*
		1.如果是正常bean: !(beanInstance instanceof FactoryBean)
			---->直接返回即可
		2.如果name前有&,到这一步说明前面的已经判断出来是FactoryBean类型 --->(||短路功能)
			---->说明用户想获取FactoryBean,也直接返回即可
	*/
	if(如果是正常的bean || name前有&){
		return beanInstance;
    }
	
	//到这里说明该bean的FactoryBean类型的,否则已经在上面的if语句中return了
	Object object = null;
	if(rbd == null){
		//尝试从缓存中加载
		object = getCachedObjectForFactoryBean(beanName);
	}
	if(object == null){
		FactoryBean<?> factory = (FactoryBean<?>)beanInstance;
		//在beanDefinitionMap中检测是否有该beanName
		if(rbd == null && containsBeanDefinition(beanName)){
			//将GenericBeanDefinition转换为RootDefinitionBean
			//如果该bean是子bean的话还会合并相应父bean的属性
			rbd = getMergedLocalBeanDefinition(beanName);
		}
		boolean synthetic = (rbd!=null & brd.isSynthetic());
		object = getObjectFromFactoryBean(factory,beanName,!synthetic );
	}
		return object;
}

从FactoryBean中解析bean:getObjectFromFactoryBean方法

if(factory.isSingleton() && containsSingleton(beanName)){
	synchronized(getSingletonMutex()){
		Object object = this.factoryBeanObjectCache.get(beanName);
		if(object == null){
			//这里调用getObject方法直接获取bean,然后做了一些后处理的工作
			object = doGetObjectFromFactoryBean(factory,beanName,shouldPostProcess);
			//用来缓存通过FactoryBean创建的单例Bean
			this.factoryBeanObjectCache.put(beanName,(object !=null ?object:NULL_OBJECT));
		}
		return (object !=NULL_OBJECT ? object : null);
	}

}else{
	return doGetObjectFromFactoryBean(factory,beanName,shouldPostProcess);
	}

3.尝试获取单例

这个步骤其实是在第2小结之前 的,也就是先尝试从单例缓存中获取bean,如果获取不到才进入第2小结的内容
入口代码:

public Object getSingleton(String beanName,ObjectFactory singletonFactory){
	
	部分不重要的代码略


	//首先是检查bean在之前是否已经被加载过
	//如果加载过直接复用之前加载的bean
	Object SingletonObject =this.singletonObjects.get(beanName);
	//如果为空才可以进行单例bean的初始化过程
	if(singletonObject == null){
		//bean初始化预处理
		beforeSinletonCreation(beanName);
		//初始化bean
		singletonObject = singltonFactory.getObject();
		//bean后处理
		afterBeanCreation(beanName);
		//加入到单例缓存中
		addSingleton(beanName,singletonObject);
	}
	return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

--------------------------------------BEAN的预处理:beforeSinletonCreation-----------------------------------------------

首先是bean的预处理:这里的预处理没有太多逻辑,只有一个作用就是记录当前bean的加载状态:

this.singletonsCurrentlyInCreation.add(beanName);

这样的话方便对后面的循环依赖进行检测

--------------------------------BEAN的创建过程:singletonObject = singltonFactory.getObject();--------------------

然后是初始化bean,也就是singltonFactory的getObject()方法,这个方法调用了createBean方法

protected Object createBean(final String beanName,final RootBeanDefinition rbd,final Object[] args){
	//根据设置的class属性或者className来解析Class
	resolveBeanClass(rbd,beanName);
	/*
		look-up和replace-method都会存在BeanDefinition中国的methodOverrides属性里面
		这个方式就是处理这个属性的
		说白了就是生成需要处理的bean的代理,做增强处理
	*/
	rbd.prepareMethodOverrides();
	/*
		经过此方法后,bean已经被增强(aop动态代理,调用后置处理器等等)
	
	*/
	Object bean  = resolveBeforeInstactiation(beanName,rbd);
	if(bean != null){
		return bean;
	}
	Object beanInstance = doCreateBean(beanName,rbd,args);

}

4.循环依赖

spring容器循环依赖包括构造器循环依赖和setter循环依赖

构造器依赖

构造器注入构成的循环依赖是无法解决的,只能通过抛出异常来解决(BeanCurrentlyInCreationException)

BeanCurrentlyInCreationException抛出检测过程分析:
	1.在bean开始创建的时候,spring会将每一个正在创建的bean的唯一标识放入一个池中,该池标识当前bean正在创建。
	2。如果在一个bean正在调用其构造器创建的时候发现自己在池中,则会抛出异常。
	3.对于已经创建完成的bean(也就是已经调用完其构造器),则会将标识符从池中移除。
	

Setter循环依赖

如果通过setter的方式注入bean,则spring通过以下方法来解决:

对于setter依赖的方式,spring采用提前暴露刚刚调用完构造器还未完成其他步骤的bean来完成,也就是暴露一个“正在创建的bean”

基于上述原因,只能解决单例的循环以来,因为多例的bean只有在其使用的时候才会创建

补:一些缓存的介绍:

/** Cache of singleton objects: bean name --> bean instance
	存放已经创建好的bean对象
 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** Cache of singleton factories: bean name --> ObjectFactory 
	存放最开始的bean对象,作用是解决循环以来,可以不等bean创建完成就注入到其他对象当中
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

/** Cache of early singleton objects: bean name --> bean instance 
	存放创建bean的工厂对象,也是用来解决循环依赖的
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

通过下面的例子演示解决循环依赖的过程:

public class A{
	private B b;
	public void setB(B b){
		this.b = b;
	}
}

public class B{
	
	private A a;
	public void setA(A a){
		this.a = a;
	}
		
}
配置略

当创建A的时候(从缓存中获取bean失败即开始创建bean)

/*rbd----> RootBeanDefinition
  instanceWrapper ---->这个相当于bean的代理类,里面通过动态代理已经对bean进行了包装(aop功能在这里实现)
*/
instanceWrapper = createBeanInstance(beanName,rbd,args);
//在这里通过反射调用bean的构造器创建bean,但是bean的属性还未注入
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrapperInstance() : null );

将调用完A的构造器的bean创建完成后,就将这个早期bean A暴露出去—>加到singletonFactories缓存中

//创建一个ObjectFactory工厂匿名内部类对象,实现了其getObject方法
addSingletonFactory(beanName,new ObjectFactory<Object>(){
		
		public Object getObject(){
			/*beanName:bean的唯一标识
			  rbd:RootBeanDefinition
			  bean:就是上面创建的那个bean--->也就是调用完构造器还未创建完成的bean A
			*/
			return getEarlyBeanReference(beanName.rbd,bean);
		}
});

然后就是对A进行属性注入:

populateBean(beanName,rbd,instanceWrapper);

当进行属性注入检测到需要注入B的时候,会去实例化B,然后调用完B的构造器后,发现需要注入A:

//获取A的早起引用
//这里其实就是尝试从缓存汇总获取单例的代码(# 1小节的代码)
protected Object getSingleton(String beanName,boolean allowEarlyReference){
	//首先尝试从singletonObjets里面获取A的实例
	//但是A还未创建完成,而SingletonObjects缓存的是beanName--->bean的完全体之间的关系
	//所以此时SingletonObject为null
	Object SingletonObject = this.singletonObjects.get(beanName);
	if(SingletonObject == null){
		synchronized(this.singletonObjects){
			//从singletonObjets获取不到
			//再次尝试从earlySingletonObjects里面获取实例
			//此时A还未加到这个缓存中,只是将ObjectFactory暴露了
			//所以这一步singleObject还是为null
			singletonObject = this.earlySingletonObjects.get(beanName);
			if(singletonObject  == null  && allowEarlyReference){
				//尝试获取创建该bean的ObjectFactory
				//这里获取到了singletonFactory ,因为在上一步已经暴露了(加入到了singletonFactories缓存中)
				ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
				if(singletonFactory  != null){
					//这里的singletonObject就是一开始创建的A,
					//调用了我们预先写好的getObject回调方法 
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName,SingletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

循环依赖结束;;;;;;


下面开始bean的真正创建的步骤:doCreateBean方法

(1)创建bean的实例

protected BeanWrapper createBeanInstance(String beanName,RootBeanDefinition rbd,Object[] args){
	//解析class
	Class beanClass = resolveBeanClass(rdb,beanName);
	if(beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !rbd.isNonPublicAccessAllowed()){
	//如果在RootBeanDefinition中有factoryMethod属性,也就是在spring文件中配置了factory-method
	//则使用instantiateUsingFactoryMethod生成bean的实例
	/*
		factory-method和factory-bean解析:
		1.使用工厂方法来创建bean:
			public class CarFactory{
				public Car createCar(){
					return new Car;
				}

			}
		<bean id="carFactory" class="CarFactory"/>
		<bean id="car" class="Car" factory-bean="carFactory" factory-method="createCar"/>

		2.静态工厂创建bean:
			public class CarFactory{
				public static Car createCar(){
					return new Car;
				}

			}
			<bean id="car" class="CarFactory" factory-method="createCar"/>
	*/
	if(rbd.getFactoryMethodName() != null){
		return instantiateUsingFactoryMethod(beanName,rbd,args);
	}
	boolean resolved = false;
	boolean autowireNecessary = false;
	if(args == null){
		synchronized(rbd.constructorArgumentLock){
			if(rbd.resolvedConstructorOrFactoryMethod != null){
				resolved = true;
				autowireNecessary = rbd.constructorArgumentsResolved;
			}
		}
	}
	if(resolved){
		if(auwireNecessary){
			return autowireCOnstructor(beanName,rbd,null,null);
		}else{
			return instantiateBean(beanName,rbd);
		}
	}
		//根据需要解析构造参数,确定构造器,实例化bean
		/*
			因为一个类可能有多个构造器,所以需要根据参数来解析需要使用那个构造器来实例化
			1.构造参数的获取(使用缓存,将以前创建bean的构造器参数缓存起来)
			2.构造器的确定
				首先对构造器排序,public在前,非public在后
				然后通过参数个数来确定,参数最多的排在第一位
				。。。
		*/
		Constructor[] ctors = determineConstrutorsFromBeanPostProcessors(beanClass,beanName);
		......

}

bean的实例化策略:
1.如果没有lookup-method和replace-method属性,直接利用反射创建bean
2.如果有,使用动态代理将这两个属性切入进去

然后调用初始化bean的一些方法和组件:比如配置了init-method或者destroy-method等等

如果实现了某些xxxAware接口,需要进行注入处理

猜你喜欢

转载自blog.csdn.net/xkshihaoren/article/details/87906203