入口:
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接口,需要进行注入处理