Spring 源码解析之FactoryBean
看一个例子
FactoryBeanDemo类
@Service
public class FactoryBeanDemo implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new FactoryB();
}
@Override
public Class<?> getObjectType() {
return FactoryB.class;
}
}FactoryB类`
public class FactoryB {
}测试代码
public void test4() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("cn.com.dq");
FactoryB factoryB = (FactoryB) applicationContext.getBean("factoryBeanDemo");
System.out.println(factoryB);
FactoryBeanDemo factoryBeanDemo = (FactoryBeanDemo) applicationContext.getBean("&factoryBeanDemo");
System.out.println(factoryBeanDemo);
}输出结果

从上面的代码可以启发2点思考
1.我们通过beanName=[factoryBeanDemo]拿到的bean不是FactoryBeanDemo的实例,而是FactoryB 的实例
2.我们要想拿到FactoryBeanDemo的实例而是通过&factoryBeanDemo拿到
下面我们从源码上分析上述情况
源码分析
首先实例化的是实现了FactoryBean接口的类
源码如下:
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}先判断是否是FactoryBean,是就在beanName前面拼接了一个&
接着就是getBean操作,getBean里面调用的是doGetBean
AbstractBeanFactory类
doGetBean()方法
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
...
final String beanName = transformedBeanName(name);
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);
}
...
}`
1.传进来的参数name是带有&的
2.String beanName = transformedBeanName(name)将&符号去掉复制给了beanName
所以此时beanName是没有&符号的,name是有&符号的
3.接着就是实例化,实例化factoryBean后,将其存在一级缓存中
4.接着FactoryBean接口方法的调用,入口是getObjectForBeanInstance();
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.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 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类型的,或者name是以&号开头的,则直接返回实例
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//如果代码能走下来,则说明 beanName不是以&开头,并且beanInstance是FactoryBean类型的
Object object = null;
if (mbd == null) {
//从缓存里面拿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;
}如下代码
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}BeanFactoryUtils的isFactoryDereference方法如下
public static boolean isFactoryDereference(@Nullable String name) {
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}1.FactoryBean首次实例化以后,此时的name参数是含有&的,代码不继续执行,返回了。
2.当用户在调用上下文getBean操作beanName加&时,此时在一级缓存拿到FactoryBean真正的实例,然后返回,所以可以解释要拿到FactoryBeanDemo的实例则是通过&factoryBeanDemo拿到
2.当用户在调用上下文getBean操作beanName不加&时,并且beanInstance是FactoryBean类型,会优先在factoryBeanObjectCache缓存中拿。
3.第一次肯定是拿不到的,则会执行getObjectFromFactoryBean()方法
FactoryBeanRegistrySupport类
getObjectFromFactoryBean()方法
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) {
//调用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;
}
}该方法执行2个比较重要的操作
1.doGetObjectFromFactoryBean()
2.将执行doGetObjectFromFactoryBean()方法返回的bean的实例放入factoryBeanObjectCache缓存中
doGetObjectFromFactoryBean()方法
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final 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;
}上述代码可以看到最终调用到了FactoryBean的getObject()方法
回到示例代码FactoryBean的getObject()的方法返回的是FactoryB的实例
通过上述的源码分析就能解释我们通过beanName=[factoryBeanDemo]拿到的bean不是FactoryBeanDemo的实例,而是FactoryB 的实例
总结
1.spring在bean的实例化时,会将实现了FactoryBean的接口进行实例化,存在一级缓存singletonObjects中,此时FactoryBean的接口的方法getObject是没有执行的
2.当执行了beanFactory.getBean()操作,如果beanName加&,则直接在一级缓存中拿到的是FactoryBean实例返回了,如果没有加&,他会执行到FactoryBean的接口的方法getObject,然后将getObject返回的实例存在factoryBeanObjectCache缓存中
3.所以bean在实现FactoryBean接口后通过beanName拿到的不是bean本身的实例而是FactoryBean接口中getObject()方法返回的实例
4.bean在实现FactoryBean接口后要拿到bean本身的实例,则是通过&+beanName拿到

浙公网安备 33010602011771号