前言

从前面得知,真正实例化并且初始化bean的地方在getBean方法中:image

今天跟大家一起聊聊getBean方法中,那些不为人知的小秘密,希望对你会有所帮助。

1 doGetBean方法

我们日常工作中,使用的getBean方法都在AbstractBeanFactory类中:image目前包含了4个重载的getBean方法。

第一个getBean方法,直接根据beanName获取bean。

第二个getBean方法,根据beanName和类的class信息,获取bean。

第三个getBean方法,根据beanName和构造器的参数,获取bean。

第四个getBean方法,根据beanName、类的class信息和构造器的参数,获取bean。

它们的底层都会调用doGetBean方法:

protected<T>TdoGetBean(Stringname,@NullableClass<T>requiredType,
        @Nullable   Object[]args,booleantypeCheckOnly) throwsBeansException{
//将name转换成beanName,去掉name前缀中的&
StringbeanName=transformedBeanName(name);
ObjectbeanInstance;


//从缓存中获取bean实例
ObjectsharedInstance=getSingleton(beanName);
//如果缓存中有bean实例,并且传入的构造参数为空
if(sharedInstance!=null&&args==null){
...
//获取真正的bean实例对象,主要是为了处理FactoryBean的情况
beanInstance=getObjectForBeanInstance(sharedInstance,name,beanName,null);
}


else{
//如果是Prototype类型的bean,则检查循环依赖
if(isPrototypeCurrentlyInCreation(beanName)){
thrownewBeanCurrentlyInCreationException(beanName);
}


//检查是否存在父BeanFactory
BeanFactoryparentBeanFactory=getParentBeanFactory();
//如果父BeanFactory存在,并且不在BeanDefinition集合中
if(parentBeanFactory!=null&&!containsBeanDefinition(beanName)){
//名字的转换:&&&xxx ->&xxx
StringnameToLookup=originalBeanName(name);
            //如果父BeanFactory是AbstractBeanFactory类型的
if(parentBeanFactoryinstanceofAbstractBeanFactory){
return((AbstractBeanFactory)parentBeanFactory).doGetBean(
nameToLookup,requiredType,args,typeCheckOnly);
}
//如果doGetBean方法传入了构造参数
elseif(args!=null){
//通过beanName和构造参数获取bean实例
return(T)parentBeanFactory.getBean(nameToLookup,args);
}
//如果doGetBean方法传入了bean的类型
elseif(requiredType!=null){
//通过beanName和requiredType获取bean实例
returnparentBeanFactory.getBean(nameToLookup,requiredType);
}
else{
//否则,只能通过beanName获取bean实例
return(T)parentBeanFactory.getBean(nameToLookup);
}
}


...

//下面是处理父BeanFactory为空的情况,大多数情况下父BeanFactory是为空的。
try{
...
//合并BeanDefinition,说白了是把某些类父类上的属性复制过来
RootBeanDefinitionmbd=getMergedLocalBeanDefinition(beanName);
//检查如果是抽象类,则不允许创建bean实例
checkMergedBeanDefinition(mbd,beanName,args);
//处理bean依赖的情况,比如:A依赖于B,要先实例化B,才能实例化A。
String[]dependsOn=mbd.getDependsOn();
if(dependsOn!=null){
for(Stringdep:dependsOn){
//从缓存中判断beanName有没有依赖,如果已经存在依赖,
                    //说明有循环依赖的情况,则抛异常
if(isDependent(beanName,dep)){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Circulardepends-onrelationshipbetween'"+beanName+"'and'"+dep+"'");
}
//如果没有依赖,则将beanName添加到缓存中
registerDependentBean(dep,beanName);
try{
//根据dep获取bean实例
getBean(dep);
}
catch(NoSuchBeanDefinitionExceptionex){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"'"+beanName+"'dependsonmissingbean'"+dep+"'",ex);
}
}
}


//创建单例类型的bean
if(mbd.isSingleton()){
sharedInstance=getSingleton(beanName,()->{
try{
returncreateBean(beanName,mbd,args);
}
catch(BeansExceptionex){
destroySingleton(beanName);
throwex;
}
});
beanInstance=getObjectForBeanInstance(sharedInstance,name,beanName,mbd);
}
//创建多例类型的bean
elseif(mbd.isPrototype()){
ObjectprototypeInstance=null;
try{
beforePrototypeCreation(beanName);
prototypeInstance=createBean(beanName,mbd,args);
}
finally{
afterPrototypeCreation(beanName);
}
beanInstance=getObjectForBeanInstance(prototypeInstance,name,beanName,mbd);
}
//创建其他类型的bean,即用户自定义的类型
else{
StringscopeName=mbd.getScope();
if(!StringUtils.hasLength(scopeName)){
thrownewIllegalStateException("Noscopenamedefinedforbean'"+beanName+"'");
}
Scopescope=this.scopes.get(scopeName);
if(scope==null){
thrownewIllegalStateException("NoScoperegisteredforscopename'"+scopeName+"'");
}
try{
ObjectscopedInstance=scope.get(beanName,()->{
beforePrototypeCreation(beanName);
try{
returncreateBean(beanName,mbd,args);
}
finally{
afterPrototypeCreation(beanName);
}
});
beanInstance=getObjectForBeanInstance(scopedInstance,name,beanName,mbd);
}
catch(IllegalStateExceptionex){
thrownewScopeNotActiveException(beanName,scopeName,ex);
}
}
}
catch(BeansExceptionex){
//清理已创建beanName的缓存
cleanupAfterBeanCreationFailure(beanName);
throwex;
}
finally{
beanCreation.end();
}
}


//校验name和传入的requiredType类型是否对应
returnadaptBeanInstance(name,beanInstance,requiredType);
}

doGetBean方法的代码很多,很多关键的地方,我增加了一些注释,帮助大家能够把有些逻辑看清楚。

下面用一张图总结一下doGetBean方法的关键逻辑:image经过梳理,逻辑还是比较清晰的。

接下来,我们一起看看几个主要的方法。

2 transformedBeanName方法

transformedBeanName方法主要是为了将name转换成beanName,去掉name前缀中的&。

image调用了BeanFactoryUtils类的transformedBeanName去除&。image

  1. 如果name中不包含&,则直接返回name。
  2. 如果name中包含了&,则循环截取去掉所有的&前缀,比如:&x变成x,&&x变成x。

3 getSingleton方法

getSingleton方法主要是为了从缓存中获取bean实例。image调用了重载的getSingleton方法,其中allowEarlyReference传入了true。

protectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference){
//从一级缓存中获取bean实例
ObjectsingletonObject=this.singletonObjects.get(beanName);
//如果bean实例为空
if(singletonObject==null&&isSingletonCurrentlyInCreation(beanName)){
//再从二级缓存中获取bean实例
singletonObject=this.earlySingletonObjects.get(beanName);
//如果bean实例还是为空,并且allowEarlyReference为true
if(singletonObject==null&&allowEarlyReference){
//加锁,为了防止并发创建bean实例的情况
synchronized(this.singletonObjects){
//再从一级缓存中获取bean实例
singletonObject=this.singletonObjects.get(beanName);//如果bean实例为空
if(singletonObject==null){
//再从二级缓存中获取bean实例
singletonObject=this.earlySingletonObjects.get(beanName);
//如果bean实例还是为空
if(singletonObject==null){
//再从三级缓存中获取ObjectFactory对象
ObjectFactory<?>singletonFactory=this.singletonFactories.get(beanName);
//如果ObjectFactory对象不为空
if(singletonFactory!=null){
//调用getObject方法获取bean实例
singletonObject=singletonFactory.getObject();//将bean实例对象加入二级缓存
this.earlySingletonObjects.put(beanName,singletonObject);
//删除三级缓存中ObjectFactory对象
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
//最后返回bean实例对象
returnsingletonObject;
}

用一张图总结一下关键流程:

image

getSingleton方法中用到了Spring的三级缓存。

  1. singletonObjects:代表一级缓存,里面保存的是实例化完成的bean实例。
  2. earlySingletonObjects:代表二级缓存,里面保存的是提前保留的bean实例,这类bean还没实例化完成。
  3. singletonFactories:代表三级缓存,里面保存的是实现了ObjectFactory接口的类。

不知道你们有没有发现,从一级缓存和二级缓存中获取bean实例,其实是获取了两次的。

第一次和第二次中间使用了synchronized关键字,这其实是双重检测锁的用法,可以提高一点性能。

4 getObjectForBeanInstance方法

getObjectForBeanInstance方法用于获取真正的bean实例对象,主要是为了处理FactoryBean的情况。

从上一篇文章得知:

  1. getBean("&myFactoryBean");获取的才是MyFactoryBean对象。
  2. getBean("myFactoryBean");获取的是MyFactoryBeanService类中getObject方法返回的对象。
  3. getBean("beanName"); 获取普通的bean对象。

因此,在getBean方法中这三种获取bean的方式都需要支持,代码在getObjectForBeanInstance方法中。

protectedObjectgetObjectForBeanInstance(
ObjectbeanInstance,Stringname,StringbeanName,@NullableRootBeanDefinitionmbd){


//判断name是否包含&前缀
if(BeanFactoryUtils.isFactoryDereference(name)){
//如果beanInstance是空bean,则直接返回
if(beanInstanceinstanceofNullBean){
returnbeanInstance;
}
//如果beanInstance不是FactoryBean,则直接抛异常
if(!(beanInstanceinstanceofFactoryBean)){
thrownewBeanIsNotAFactoryException(beanName,beanInstance.getClass());
}
if(mbd!=null){
mbd.isFactoryBean=true;
}
//直接返回beanInstance
returnbeanInstance;
}


//如果name不包含&前缀,并且beanInstance不是FactoryBean类型
//则说明beanInstance是普通的bean,则直接返回beanInstance
if(!(beanInstanceinstanceofFactoryBean)){
returnbeanInstance;
}


Objectobject=null;
if(mbd!=null){
mbd.isFactoryBean=true;
}
else{
//从FactoryBean缓存中获取bean实例
object=getCachedObjectForFactoryBean(beanName);
}
//如果bean实例为空
if(object==null){
FactoryBean<?>factory=(FactoryBean<?>)beanInstance;
if(mbd==null&&containsBeanDefinition(beanName)){
mbd=getMergedLocalBeanDefinition(beanName);
}
booleansynthetic=(mbd!=null&&mbd.isSynthetic());
//调用FactoryBean对象的getObject方法获取bean实例
object=getObjectFromFactoryBean(factory,beanName,!synthetic);
}
//返回bean实例
returnobject;
}

下面用一张图总结一下关键流程:

image

未完待续。。。

最后修改:2026 年 06 月 05 日
如果觉得我的文章对你有用,请随意赞赏