Java教程

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拿到
下面我们从源码上分析上述情况

源码分析

在bean的实例化中,当bean实例化完成以后都会看到这样一行代码,如下:

AbstractBeanFactory类

doGetBean()方法

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                              @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		 ...
        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接口的调用入口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.上述代码可以解释要拿到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拿到

这篇关于Spring 源码解析之FactoryBean的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!