10Spring 源码学习 ~ Bean 的加载步骤详解
Posted 戴泽supp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10Spring 源码学习 ~ Bean 的加载步骤详解相关的知识,希望对你有一定的参考价值。
Bean 的加载步骤详解(一)
一、FactoryBean 的使用
一般情况下,Spring 通过反射机制,利用 bean 的 class 属性指定的实现类,来实例化 bean。但假如实例化的 bean 需要配置文件提供大量的信息,这个时候配置文件的灵活方式是受限的,此时采用编码的方式也许可得到一个简单的方案。Spring 为此提供了一个 FactoryBean 的工厂类接口,用户可以通过实现该接口,来定制实例化 bean 的逻辑。
Spring 本生提供了 70 多个 FactoryBean 的实现,而且从 Spring 3.0 开始,FactoryBean 可支持泛型,即接口声明改为 FactoryBean<T>
的形式。如下:
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T>
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
//返回由 FactoryBean 创建的 bean 实例,如果 isSingleton 返回 true,则该实例会放到 Spring 容器中的单例缓存池中
@Nullable
T getObject() throws Exception;
//返回由 FactoryBean 创建的 bean 类型
@Nullable
Class<?> getObjectType();
//返回 FactoryBean 创建的 bean 实例的作用域,默认是单例 singleton
default boolean isSingleton()
return true;
当 <bean>
中的 class 属性是 FactoryBean 的实现类时,通过 getBean() 方法返回的不是 FactoryBean 本身,而是 FactoryBean#getObject 返回的对象。
示例:
Car.java
package com.luo.spring.guides.helloworld.beanloading.factorybean;
import lombok.Data;
import lombok.ToString;
/**
* @author : archer
* @date : Created in 2022/10/28 10:27
* @description :
*/
@Data
@ToString
public class Car
//最大速度
private int maxSpeed;
//品牌
private String brand;
//价格
private double price;
CarFactoryBean.java
package com.luo.spring.guides.helloworld.beanloading.factorybean;
import org.springframework.beans.factory.FactoryBean;
/**
* @author : archer
* @date : Created in 2022/10/28 10:28
* @description :
*/
public class CarFactoryBean implements FactoryBean<Car>
private String carInfo;
@Override
public Car getObject() throws Exception
Car car = new Car();
String[] infos = carInfo.split(",");
car.setBrand(infos[0]);
car.setMaxSpeed(Integer.parseInt(infos[1]));
car.setPrice(Double.parseDouble(infos[2]));
return car;
@Override
public Class<?> getObjectType()
return Car.class;
@Override
public boolean isSingleton()
return false;
public String getCarInfo()
return carInfo;
//接受逗号分隔符设置属性信息,并且顺序固定是 brand,maxSpeed,price
public void setCarInfo(String carInfo)
this.carInfo = carInfo;
facotryBeanTest.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car" class="com.luo.spring.guides.helloworld.beanloading.factorybean.CarFactoryBean">
<property name="carInfo" value="超级跑车,400,2000000"/>
</bean>
</beans>
Main.java
package com.luo.spring.guides.helloworld.beanloading.factorybean;
import com.luo.spring.guides.helloworld.common.TestBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author : archer
* @date : Created in 2022/10/28 10:49
* @description :
*/
public class Main
public static void main(String[] args)
ApplicationContext bf = new ClassPathXmlApplicationContext("beanloading/factorybean/facotryBeanTest.xml");
//获取 Car 实例
Car car = (Car) bf.getBean("car");
System.out.println(car);
//获取 CarFactoryBean 实例
CarFactoryBean carFactoryBean = (CarFactoryBean) bf.getBean("&car");
System.out.println(carFactoryBean.getClass());
输出:
Car(maxSpeed=400, brand=超级跑车, price=2000000.0)
class com.luo.spring.guides.helloworld.beanloading.factorybean.CarFactoryBean
二、缓存中获取单例 bean
单例 bean 的加载只会在 Spring 的容器中创建一次,后续再获取是直接从缓存中获取。这里首先是从缓存中加载,不存在再去 singleFactories 中加载。这里 Spring 为了避免循环,它创建 bean 的原则是不等 bean 创建完成,就会将创建 bean 的 ObjectFactory 提早曝光加入到缓存中,一旦下个 bean 创建时需要依赖上个 bean,则直接使用 ObjectFactory。
@Override
@Nullable
public Object getSingleton(String beanName)
//参数 true 表示允许早期依赖
return getSingleton(beanName, true);
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference)
// Quick check for existing instance without full singleton lock
//检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
//缓存还不存在单例 bean 并且当前正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
//判断早期依赖中是否存在实例,有则表示 bean 正在加载
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference)
//不存在并且允许早期依赖,则锁定全局变量并进行处理
synchronized (this.singletonObjects)
// Consistent creation of early reference within full singleton lock
//双重判断缓存中是否存在实例,防止上层判断完后准备加锁的时候,另一线程已实例化,并放到缓存中了
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null)
//当某些 bean 需要提前初始化的时候,则会调用 addSingleFactory 方法将对应的
//ObjectFactory 初始化策略,存储在 singletonFactories中
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null)
//调用预先设定的 getObject 方法
singletonObject = singletonFactory.getObject();
//记录在缓存中,earlySingletonObjects 与 singletonFactories 互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
return singletonObject;
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects)
if (!this.singletonObjects.containsKey(beanName))
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
名词解释:
- **singletonObjects:**Map 结构,用于保存 BeanName 和创建 bean 实例之间的关系,beanName -> bean instance;
- **singletonFactories:**Map 结构,用于保存 BeanName 和创建 bean 实例的工厂之间的关系,beanName -> ObjectFactory;
- **earlySingletonObjects:**Map 结构,用于保存 BeanName 和创建 bean 实例之间的关系
- 与 singletonObjects 不同之处在于,当一个单例 bean 被放到里面后,那么当 bean 还在创建过程中时,就可以通过 getBean 方法获取到了,其目的是用来检测循环引用。
- **registeredSingletons:**Set 结构,用来保存当前所有已注册的单例 beanName;
上述代码大致步骤如下:
- 1、首先尝试从 singletonObjects 中获取实例
- 2、若上面获取不到,再尝试从 earlySingletonObjects 中获取实例
- 3、若还是获取不到并且 allowEarlyReference 为 true (允许循环引用)时,再从 singletonFactories 中获取对应的 ObjectFactory,在调用这个 ObjectFactory 的 getObject 来创建 bean,并放到 earlySingletonObjects 缓存中去,并从 singletonFactories 中 remove 掉这个 ObjectFactory。
三、从 bean 的实例中获取对象
在 getBean 的方法中,getObjectForBeanInstance 是个高频率使用的方法。无论是从缓存中还是根据不同的 scope 策略得到 bean 实例后,首先做的都是调这个方法来检测下正确性,即当前 bean 是否是 FactoryBean 类型的 bean,如果是,则调用对应的 FactoryBean 实例中的 getObject() 作为返回值。
这里返回的只是 bean 最原始的状态。并不一定是我们真正需要的 bean。
如:假如我们需要对工厂 bean 进行处理,这里得到的是工厂 bean 的初始状态,而我们真正需要的是工厂 bean 中定义的 factory-method 方法中返回的 bean。而 getObjectForBeanInstance 就是完成这个工作的。源码如下:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//如果指定的 name 是工厂相关(以 & 为前缀),则进入代码
if (BeanFactoryUtils.isFactoryDereference(name))
if (beanInstance instanceof NullBean)
return beanInstance;
//beanInstance 不是 FactoryBean 类型,则验证不通过
if (!(beanInstance instanceof FactoryBean))
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
if (mbd != null)
mbd.isFactoryBean = true;
//getBean("&car"); 直接返回 FactoryBean
return beanInstance;
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//现在这个 beanInstance 可能是普通的 bean 实例或者 FactoryBean 对象,
//如果是普通的 bean,则直接返回
if (!(beanInstance instanceof FactoryBean))
return beanInstance;
//加载 FactoryBean
Object object = null;
if (mbd != null)
mbd.isFactoryBean = true;
else
//尝试从缓存中加载 bean
object = getCachedObjectForFactoryBean(beanName);
if (object == null)
// Return bean instance from factory.
//到这里已经明确知道 beanInstance 一定是 FactoryBean 类型
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//containsBeanDefinition 检测 beanDefinitionMap (即所有已加载的类)中检测是否定义了 beanName
if (mbd == null && containsBeanDefinition(beanName))
//将存储 XML 配置文件的 GernericBeanDefinition 转换为 RootBeanDefinition,
//如果指定 beanName 是子 Bean 的话,同时会合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
//是否是用户定义的,而不是程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
//用户自定义的无需后置处理
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
return object;
上述中主要是做一些功能性的判断检查,大致如下:
- 1、验证 FactoryBean 的正确性
- 2、非 FactoryBean 不做任何处理
- 3、对 bean 进行转换
- 4、将从 Factory 中解析 bean 的工作委托给 getObjectFromFactoryBean。
即真正核心代码委托给了 getObjectFromFactoryBean,其源码如下:
//shouldPostProcess 为 true,表示需要后置处理
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)
//如果是单例模式
if (factory.isSingleton() && containsSingleton(beanName))
synchronized (getSingletonMutex())
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null)
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null)
object = alreadyThere;
else
if (shouldPostProcess)
if (isSingletonCurrentlyInCreation(beanName))
// Temporarily return non-post-processed object, not storing it yet..
return object;
beforeSingletonCreation(beanName);
try
//调用 ObjectFactory 的后处理器
object = postProcessObjectFromFactoryBean(object, beanName);
catch (Throwable ex)
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
finally
afterSingletonCreation(beanName);
if (containsSingleton(beanName))
this.factoryBeanObjectCache.put(beanName, object);
return object;
else
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess)
try
//调用 ObjectFactory 的后处理器
object = postProcessObjectFromFactoryBean(object, beanName);
catch (Throwable ex)
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
return object;
这个方法里的逻辑就是,保证返回的 bean,如果是单例的,就是全局唯一的,同时加了一些缓存以提高性能,而获取真正实例对象的逻辑在 doGetObjectFromFactoryBean 方法中,当 bean 声明为 FactoryBean 类型时,提取 bean 时,提取的并不是 FactoryBean,而是 FactoryBean 中对应的 getObject 方法返回的 bean,doGetObjectFromFactoryBean 正是实现这个功能的,doGetObjectFromFactoryBean 源码如下:
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException
Object object;
try
//需要权限验证
if (System.getSecurityManager() != null)
AccessControlContext acc = getAccessControlContext();
try
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
catch (PrivilegedActionException pae)
throw pae.getException();
else
//直接调用 getObject 方法返回
object = factory.getObject();
catch (FactoryBeanNotInitializedException ex)
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
catch (Throwable ex)
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null)
if (isSingletonCurrentlyInCreation(beanName))
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
object = new NullBean();
return object;
处理完 doGetObjectFromFactoryBean 之后,程序还做了一些后置处理,即 shouldPostProcess 为 true 时的逻辑,先看 AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean,源码如下:
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName)
return applyBeanPostProcessorsAfterInitialization(object, beanName);
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors())
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current Spring源码学习bean的加载