前言
在【Spring源码学习】Spring Bean实例化过程-创建Bean实例 一文中,实例在真正创建完成(完成了创建、依赖属性注入、初始化)后,会有FactoryBean的接口调用,我们先定位到这段代码来看看,本章也主要跟一下这个调用的流程。
//AbstractBeanFactory
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
// 获取一个beanName,处理两种情况,一个是前面说的 FactoryBean (前面带 '&'),
// 一个是别名问题,因为这个方法是 getBean,获取 Bean 用的,你要是传一个别名进来,是完全可以的
String beanName = transformedBeanName(name);
Object bean;
/*
* Description : 检查缓存中或者实例工厂中是否有对应的实例
* 因为在创建单例 bean的时候会存在依赖注入,而在创建依赖的时候为了避免循环依赖,
* spring创建bean的原则是:不等 bean 创建完成就将创建bean的 ObjectFactory 提早曝光,
* 换句话说,也就是将 ObjectFactory 加入到缓存中,一旦下一个bean创建的时候需要依赖上
* 一个bean则直接使用 ObjectFactory
*
* 第一次getSingleton(beanName)
*/
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//如果缓存里面能拿到实例,但第一次缓存中是没有的,所以第一次不会进入这个if
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 该方法是 FactoryBean 接口的调用入口
// 如果是普通 Bean 的话,直接返回 sharedInstance(直接返回对象本身)
// 如果是 FactoryBean 的话,返回它创建的那个实例对象(返回指定方法返回的实例)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果singletonObjects缓存里面没有,则走下来
else {
//如果是scope 是Prototype的,校验是否有出现循环依赖,如果有则直接报错
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//检查一下这个 BeanDefinition 在容器中是否存在
BeanFactory parentBeanFactory = getParentBeanFactory();
//......省略部分代码
//要开始创建bean了,分两种情况:一种是针对单例的(singleton),一种是针对多例的(prototype),一种是自定义scope的
try {
//父子BeanDefinition合并
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//获取依赖对象属性,依赖对象要先实例化
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
//......省略部分代码
//单例情况singleton,着重看,大部分是单例的情况
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
//该方法是FactoryBean接口的调用入口
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//多例情况prototype
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
//该方法是FactoryBean接口的调用入口
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
//......省略部分代码
return (T) bean;
}
bean = getObjectForBeanInstance()方法就是FactoryBean接口的调用入口了。而这个接口首次调用则是在创建完成一个可用的bean之后,也就是在下面这个代码里首次调用的(本章主要针对单例,其他多例、自定义scope类似)
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;
}
});
//该方法是FactoryBean接口的调用入口
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
一、FactoryBean接口的调用
1.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.
//以&开头,针对本身就是FactoryBean的判断
//如果要获取到FactoryBean 类本身,就必须加上”&”符号,比如beanFactory.getBean(“&beanName”),
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
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.
//如果实例不是FactoryBean类型的
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
//如果代码能走下来,则说明 beanName不是以&开头,并且beanInstance是FactoryBean类型的
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//从缓存里面拿FactoryBean类型的实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//重点看
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
这里有两种情况下的返回
- 直接返回原对象:针对bean实例本身就是FactoryBean类型或者beanName是以&开头的情况
- 返回factoryBean:beanName不是以&开头,并且beanInstance是FactoryBean类型的,这里又分情况:
- 从factoryBeanObjectCache缓存中获取
- 缓存中不存在该bean,则调用factory的getObject()方法,并且判断一级缓存中如果存在该bean 实例把实例缓存到factoryBeanObjectCache 对应的map 中,这个是单独缓存FactoryBean 类型实例的map
2.getObjectFromFactoryBean(),doGetObjectFromFactoryBean()
//FactoryBeanRegistrySupport
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//factory是单例且一级缓存中存在
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//调用getObject方法
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 {
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)) {
//把实例缓存到factoryBeanObjectCache map中,这个是单独缓存FactoryBean类型实例的map
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
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;
}
BeanFactory.getBean(“beanName”)只能获取到getObject()方法返回的实例。getObject 方法返回的实例会有单独的缓存存储,跟其他实例不是同一个缓存,对应的缓存是:factoryBeanObjectCache。
二、总结
- FactoryBean 接口的首次调用入口在实例化、IOC/DI 以及初始化做完后,就会调用FactoryBean 类型的接口
- 如果要获取到FactoryBean 类本身,就必须加上”&”符号,比如beanFactory.getBean(“&beanName”)
- factoryBean有单独的缓存factoryBeanObjectCache,跟其他实例不是同一个
有关FactoryBean的作用和例子可以参考这位大佬写的例子-Spring 源码学习 FactoryBean