1. 程式人生 > 其它 >Spring 原始碼解析之FactoryBean

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介面的類

在beanName前面拼接了一個&

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);
						}
					}
				}

在bean的例項化中,當bean例項化完成以後都會看到這樣一行程式碼,如下:

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);
        }
		 ...
    }`
	

此時有個beanName,name;beanName是沒有&符號的,name是有&符號的
factoryBean這個類本身例項化完成以後放在一級快取中,factoryBean例項化完成以後
接著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例項化完成以後就返回了,如果執行getBean操作,beanName加了&此時在一級快取拿到FactoryBean真正的例項,然後返回,所以可以解釋要拿到FactoryBeanDemo的例項則是通過&factoryBeanDemo拿到
2.如果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.FactoryBean介面的呼叫入口是在bean的例項化完成以後
2.bean在實現FactoryBean介面後通過beanName拿到的不是bean本身的例項而是FactoryBean介面中getObject()方法返回的例項
3.bean在實現FactoryBean介面後要拿到bean本身的例項,則是通過&+beanName拿到
4.FactoryBean優先例項化,例項化完成以後存在一級快取singletonObjects中,接著會呼叫FactoryBean的getObject方法,將使用者自己new的例項存在factoryBeanObjectCache快取中
5.在getBean的時候,加了&,就是在spring一級快取拿到例項後,直接返回了,如果沒加&,就會在factoryBeanObjectCache快取中拿,拿到以後返回,沒有就呼叫FactoryBean的介面方法getObject返回,然後更新factoryBeanObjectCache快取