一般情况下,Spring 通过反射机制,利用 bean 的 class 属性指定的实现类,来实例化 bean。但假如实例化的 bean 需要配置文件提供大量的信息,这个时候配置文件的灵活方式是受限的,此时采用编码的方式也许可得到一个简单的方案。Spring 为此提供了一个 FactoryBean 的工厂类接口,用户可以通过实现该接口,来定制实例化 bean 的逻辑。
Spring 本生提供了 70 多个 FactoryBean 的实现,而且从 Spring 3.0 开始,FactoryBean 可支持泛型,即接口声明改为 FactoryBean
的形式。如下:
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;
}
}
当
中的 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
<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 的加载只会在 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);
}
}
}
名词解释:
上述代码大致步骤如下:
在 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;
}
上述中主要是做一些功能性的判断检查,大致如下:
即真正核心代码委托给了 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 == null) {
return result;
}
result = current;
}
return result;
}
对于后处理器的使用,后续会有详细介绍,这里我们先记住 Spring 中获取 bean 的规则:
尽可能保证所有 bean 初始化后,都会调用注册的 BeanPostProcessor#postProcessAfterInitialization 方法进行处理
实际开发过程中,可根据此特性设计自己的业务逻辑。
上面我们学习了从缓存中获取单例的过程,那如果缓存中不存在已经加载的单例 bean,那就需要从头开始 bean 的加载过程了,而 Spring 中使用 getSingleton 的重载方法实现 bean 的加载过程。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//全局变量需要加同步锁
synchronized (this.singletonObjects) {
//首先检查对应的 bean 是否已经加载过,因为 singleton 模式其实就是复用已创建的 bean
//故此步骤是必须的
Object singletonObject = this.singletonObjects.get(beanName);
//如果为空,才可以进行 singleton 的 bean 的初始化
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//初始化 bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
//加入缓存
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
//单例创建的前置处理
//记录加载状态,this.singletonsCurrentlyInCreation.add(beanName) 将 正在创建的 bean 记录到缓存中,以便对循环依赖进行检测
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
//单例创建的后置处理
//将结果记录至缓存并删除加载 bean 过程中所记录的各种辅助状态
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
//
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
上述代码使用的回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,这些准备包括如下内容:
上面我们并没有看到真正获取单例 bean 的方法,其真正实现逻辑实是在生成 ObjectFactory 的实例中实现的,如下:
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
从上面可以看出,我们需要具体到 createBean 方法中探寻真正创建 bean 的逻辑。
我们跟踪了很多 Spring 源码后,可以发现一个真正干活的函数,一般是以 do 开头的,我们看下 createBean 方法的具体实现:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//锁定 class,根据设置的 class 属性或者根据 className 来解析 class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
//验证准备重写(覆盖)的方法
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//给 BeanPostProcessors(后置处理器) 一个机会来返回代理(替代真正的实例)
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//真正创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
以上代码的具体步骤如下:
查看 AbstractBeanDefinition#prepareMethodOverrides#prepareMethodOverrides 方法:
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exist and determine their overloaded status.
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
//获取对应类中对应方法名的个数
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
//当前类中的方法只有一个,设置重载该方法没有被重载,以便后续调用,可以直接使用找到的方法,并且可以提前对方法存在性进行验证
//标记 MethodOverride 暂未被重写(覆盖),避免参数类型校验的开销
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false);
}
}
从这里可以看出 lookup-method 和 replace-method 功能的实现原理,就是在 bean 实例化时,如果检测存在 methodOverrides,就会动态地位当前 bean 生成代理,并使用对应的拦截器为 bean 做增强处理,相关逻辑实现在 bean 的实例化部分,后面会详细介绍。
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
//如果尚未被解析
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
applyBeanPostProcessorsBeforeInstantiation 是对后处理器中所有的 InstantiationAwareBeanPostProcessor 类型的后处理器进行 postProcessBeforeInstantiation 方法的调用。
applyBeanPostProcessorsAfterInitialization 是对所有 BeanPostProcessor 的 postProcessAfterInitialization 方法进行调用。
bean 的实例化前调用,也就是将 AbstractBeanDefinition 转换成 BeanWrapper 前的处理。这里是给子类一个修改 BeanDefinition 的机会,当经过这个方法后,bean 可能会成为一个经过处理的代理 bean,可能是通过 cglib 生成的,也可能是其他技术生成的。
//在实例化之前应用 BeanPostProcessors
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
}
@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 == null) {
return result;
}
result = current;
}
return result;
}