在前两篇《Spring5源码浅析(七)—DefaultSingletonBeanRegistry(上)》和《Spring5源码浅析(七)—DefaultSingletonBeanRegistry(下)》中,我给大家详细分析了DefaultSingletonBeanRegistry这个类,从中我们知道DefaultSingletonBeanRegistry主要侧重于Bean的注册,销毁,以及依赖关系(关联关系)的注册和销毁。本篇呢,我们继续沿着DefaultListableBeanFactory的继承线往下移,所以我们来看一下DefaultSingletonBeanRegistry的子类---FactoryBeanRegistrySupport.
我们首先来看这个抽象类中,最长的方法getObjectFromFactoryBean,源码如下所示:
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject to post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
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 {
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 {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
在getObjectFromFactoryBean函数中,主要处理两个问题,第一个是工厂是不是单例的,第二个是这个Bean是否需要进一步处理.
首先,如果传入的工厂是单例的,并且要获取的beanName已经被实例化了,就会使用父类DefaultSingletonBeanRegistry的getSingletonMutex来锁定singletonObjects这个集合(该集合的详细介绍可参考《Spring5源码浅析(七)—DefaultSingletonBeanRegistry(上)》),然后首先从缓存factoryBeanObjectCache中获取bean,如果缓存中已经有了,就直接返回该对象.如果缓存中没有,就调用doGetObjectFromFactoryBean方法来获取object,调用完成之后,因为有可能在调用doGetObjectFromFactoryBean的过程中,该Bean被放到了factoryBeanObjectCache中,所以需要再次校验,如果此时发现缓存中已经有了,那就直接返回就行了,如果此时还没有,我们就会判断一下在父类DefaultSingletonBeanRegistry中的singletonObjects是否已经包含该实例了,如果已经包含了,我们就把这个对象存放到本地缓存(factoryBeanObjectCache)中,在存放缓存之前,会根据shouldPostProcess来决定是否对当前这个对象做进一步的操作,比如为当前这个对象应用beforeSingletonCreation,调用postProcessObjectFromFactoryBean,以及afterSingletonCreation这几个函数.
其次,如果工厂不是单例的或者要获取的beanName没有被实例化,就会使用doGetObjectFromFactoryBean来获取实例,并根据shouldPostProcess来决定是否为这个对象执行postProcessObjectFromFactoryBean这个函数,最后进行返回.
现在来看FactoryBeanRegistrySupport中第二长的函数doGetObjectFromFactoryBean,源码如下所示:
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
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
这个方法看似很长,但实际上就做了一件事儿,就是调用传入的FactoryBean的getObject方法获取一个对象,如果FactoryBean中没有获取到,那就先看这个Bean是不是在创建中,如果是,就抛出一个异常,如果不是,就返回一个NullBean();
现在我们来看剩下的几个方法,源码如下所示:
/**
* Determine the type for the given FactoryBean.
* @param factoryBean the FactoryBean instance to check
* @return the FactoryBean's object type,
* or {@code null} if the type cannot be determined yet
*/
@Nullable
protected Class> getTypeForFactoryBean(final FactoryBean> factoryBean) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction>)
factoryBean::getObjectType, getAccessControlContext());
}
else {
return factoryBean.getObjectType();
}
}
catch (Throwable ex) {
// Thrown from the FactoryBean's getObjectType implementation.
logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
"that it should return null if the type of its object cannot be determined yet", ex);
return null;
}
}
/**
* Obtain an object to expose from the given FactoryBean, if available
* in cached form. Quick check for minimal synchronization.
* @param beanName the name of the bean
* @return the object obtained from the FactoryBean,
* or {@code null} if not available
*/
@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
/**
* Post-process the given object that has been obtained from the FactoryBean.
* The resulting object will get exposed for bean references.
* The default implementation simply returns the given object as-is.
* Subclasses may override this, for example, to apply post-processors.
* @param object the object obtained from the FactoryBean.
* @param beanName the name of the bean
* @return the object to expose
* @throws org.springframework.beans.BeansException if any post-processing failed
*/
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
return object;
}
/**
* Get a FactoryBean for the given bean if possible.
* @param beanName the name of the bean
* @param beanInstance the corresponding bean instance
* @return the bean instance as FactoryBean
* @throws BeansException if the given bean cannot be exposed as a FactoryBean
*/
protected FactoryBean> getFactoryBean(String beanName, Object beanInstance) throws BeansException {
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanCreationException(beanName,
"Bean instance of type [" + beanInstance.getClass() + "] is not a FactoryBean");
}
return (FactoryBean>) beanInstance;
}
/**
* Overridden to clear the FactoryBean object cache as well.
*/
@Override
protected void removeSingleton(String beanName) {
synchronized (getSingletonMutex()) {
super.removeSingleton(beanName);
this.factoryBeanObjectCache.remove(beanName);
}
}
/**
* Overridden to clear the FactoryBean object cache as well.
*/
@Override
protected void clearSingletonCache() {
synchronized (getSingletonMutex()) {
super.clearSingletonCache();
this.factoryBeanObjectCache.clear();
}
}
/**
* Return the security context for this bean factory. If a security manager
* is set, interaction with the user code will be executed using the privileged
* of the security context returned by this method.
* @see AccessController#getContext()
*/
protected AccessControlContext getAccessControlContext() {
return AccessController.getContext();
}
第一个getTypeForFactoryBean是为了获取factoryBean中的ObjectType.
第二个getCachedObjectForFactoryBean则是从缓存(factoryBeanObjectCache)中获取一个指定Bean.
第三个postProcessObjectFromFactoryBean,为给定的Bean做后继处理,这里是空的,但因为他的修饰符是protected,所以在子类,肯定有对他的处理.
第四个getFactoryBean,获取给定Bean的FactoryBean,这里处理的方式也很简单,就只是对给定的beanInstance做了一次强制转换,当然如果beanInstance不是FactoryBean的子类,就直接抛出异常.
第五个removeSingleton,这个函数是对父类DefaultSingletonBeanRegistry中removeSingleton的一个重载覆盖,他除了执行父类的removeSingleton之外,另外做了一个本地缓存的移除.
同样,第六个clearSingletonCache,这个函数也是对父类DefaultSingletonBeanRegistry中clearSingletonCache的一个覆盖,他除了执行父类的clearSingletonCache逻辑之外,还对本地缓存做了一个清除.
最后一个就是getAccessControlContext.说起这个函数,我们不得不提一下,如果大家注意的话,无论是getTypeForFactoryBean还是doGetObjectFromFactoryBean,亦或是getAccessControlContext,都使用了JDK所提供的资源权限控制,更倾向于从操作系统层面来强调资源调度上下文的使用,这是我们在研发的时候极少考虑的.
好了,我们对FactoryBeanRegistrySupport类的分析就到这里,如果你有什么问题或者有什么好的建议,欢迎留言或email([email protected]).我们下次将为大家分析AbstractBeanFactory.