这篇文章我们来分析一下从容器中拿FactoryBean时,返回的为什么是FactoryBean所包裹的对象,关于FactoryBean的使用,请移步:Spring中FactoryBean的使用这篇文章。将Spring中FactoryBean的使用中的例子拿过来作为源码分析的入口:
package com.luban.factoryBean;
@Component("schoolFactory")
public class SchoolFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new School();
}
@Override
public Class<?> getObjectType() {
return School.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
@Configuration
@ComponentScan("com.luban.factoryBean")
public class Config {
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext contextnew = new AnnotationConfigApplicationContext(Config.class);
School school = (School) contextnew.getBean("schoolFactory");
System.out.println(school);
SchoolFactoryBean schoolFactoryBean = (SchoolFactoryBean) contextnew.getBean("&schoolFactory");
System.out.println(schoolFactoryBean);
}
}
打印结果:
com.luban.School@3834d63f
com.luban.factoryBean.SchoolFactoryBean@1ae369b7
在将源码之前先说几个重要的点:
1.Spring中所有的单例对象都会保存在一个Map中,这个类叫做DefaultSingletonBeanRegistry ,关于DefaultSingletonBeanRegistry 是Spring中bean工厂的一个抽象类,而singletonObjects 就是存放所有单实例bean的Map,所以说在进行扫描注解的时候,会把名称为schoolFactory的SchoolFactoryBean 类型的bean添加到singletonObjects (注意虽然我们是通过bean名称为schoolFactory,来拿到School对象的,但是在这个singletonObjects 中存放的却是SchoolFactoryBean 类型的类)。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** Cache of singleton objects: bean name --> bean instance */
//用于存放完全初始化好的 bean从该缓存中取出的 bean可以直接使用
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
//存放 bean工厂对象解决循环依赖
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
//存放原始的bean对象用于解决循环依赖,注意:存到里面的对象还没有被填充属性
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//其他的进行省略
}
2. FactoryBean内部包裹的类是存在一个FactoryBeanRegistrySupport类的名称叫做factoryBeanObjectCache的Map中的,关于FactoryBeanRegistrySupport是DefaultSingletonBeanRegistry 的子类,在AnnotationConfigApplicationContext 中有个bean工厂会间接的继承FactoryBeanRegistrySupport。
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
/** Cache of singleton objects created by FactoryBeans: FactoryBean name --> object */
//缓存factoryBean包裹的Object对象
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
//省略其他部分
}
3.通过截图真实的比较一下差异
我们可以看到在未执行School school = (School) contextnew.getBean("schoolFactory")之前,factoryBeanObjectCache 中是没有数据的。
当断点执行到http://SchoolFactoryBean schoolFactoryBean = (SchoolFactoryBean) contextnew.getBean("&schoolFactory")时,factoryBeanObjectCache 有了一条数据。
4. 所以当我们向Spring中注入FactoryBean类型的bean,相当于注入了两个bean(另外一个虽然不在singletonObjects中,但是也受Spring的管理),并且被FactoryBean包裹的bean具有天然的懒加载功能,通过上图得知的。
5.在singletonObjects中的schoolFactory类型为SchoolFactoryBean的bean,和普通的bean注入容器的方式一样,也可以从上图得知,在Spring进行扫描并注入到Spring容器的时候不回去考虑是不是FactoryBean类型的bean,所以注入到容器的过程就不在分析,在此只分析getBean的过程。
FactoryBean源码分析:
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext contextnew = new AnnotationConfigApplicationContext(Config.class);
School school = (School) contextnew.getBean("schoolFactory");
System.out.println(school);
SchoolFactoryBean schoolFactoryBean = (SchoolFactoryBean) contextnew.getBean("&schoolFactory");
System.out.println(schoolFactoryBean);
}
}
首先入口为contextnew.getBean("schoolFactory")方法,然后会调用到AbstractApplicationContext#getBean方法:
@Override
public Object getBean(String name) throws BeansException {
//判断容器是否处于激活状态
assertBeanFactoryActive();
//首先获得容器,然后调用容器的getBean方法
return getBeanFactory().getBean(name);
}
AbstractBeanFactory#getBean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
/**
* 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两个原因
* 1、name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean
* 实现类所创建的 bean。在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储
* 方式是一致的,即 <beanName, bean>,beanName 中是没有 & 这个字符的。所以我们需要
* 将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。
* 2、还是别名的问题,转换需要
* 如果name是以 & 字符开头,那么转换后的值赋给了beanName,此时beanName 对应得是singletonObjects里面的key
*/
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
/**
* 这个方法在初始化的时候会调用,在getBean的时候也会调用
* 为什么需要这么做呢?
* 也就是说spring在初始化的时候先获取这个对象
* 判断这个对象是否被实例化好了(普通情况下绝对为空====有一种情况可能不为空)
* 从spring的bean容器中获取一个bean,由于spring中bean容器是一个map(singletonObjects)
* 所以你可以理解getSingleton(beanName)等于beanMap.get(beanName)
* 由于方法会在spring环境初始化的时候(就是对象被创建的时候调用一次)调用一次
* 还会在getBean的时候调用一次
* 所以再调试的时候需要特别注意,不能直接断点在这里,
* 需要先进入到annotationConfigApplicationContext.getBean(IndexDao.class)
* 之后再来断点,这样就确保了我们是在获取这个bean的时候调用的
*
* 需要说明的是在初始化时候调用一般都是返回null
* 因为我们这次实是在容器加载之后进行的,所以可以从容器中直接拿到对象
*/
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
/**
* 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果
* sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的
* bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回
* 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
* 如果name传过来的是以&开头的或者是别名,那么name和beanName就不相等了,beanName是转换后的值
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//省略从单例池中获取不到时,开始创建bean的过程
}
return (T) bean;
}
我们来看一下getSingleton是如何拿到缓存的bean的,执行DefaultSingletonBeanRegistry#getSingleton方法
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从map中获取bean如果不为空直接返回,不再进行初始化工作
//因为在singletonObject中能够拿到对象,然后就直接返回了
Object singletonObject = this.singletonObjects.get(beanName);
//下面这段代码会在循环依赖中应用到,先不介绍
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
在判断sharedInstance不为空的时候,会进入getObjectForBeanInstance进行进一步判断,AbstractBeanFactory#getObjectForBeanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 如果name以“&”为前缀,但是beanInstance不是FactoryBean,则抛异常
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.
// 如果beanInstance不是FactoryBean(也就是普通bean),则直接返回beanInstance
// 如果beanInstance是FactoryBean,并且name以“&”为前缀,则直接返回beanInstance(以“&”为前缀代表想获取的是FactoryBean本身)
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 走到这边,代表beanInstance是FactoryBean,但name不带有“&”前缀,表示想要获取的是FactoryBean创建的对象实例
Object object = null;
if (mbd == null) {
//如果mbd为空,则尝试从factoryBeanObjectCache缓存中获取该FactoryBean创建的对象实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
// 只有beanInstance是FactoryBean才能走到这边,因此直接强转
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
// mbd为空,但是该bean的BeanDefinition在缓存中存在,则获取该bean的MergedBeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
// mbd是否是合成的(这个字段比较复杂,mbd正常情况都不是合成的,也就是false,什么时候才是合成的,当使用AOP动态代理生成的bean,这个字段就是true
boolean synthetic = (mbd != null && mbd.isSynthetic());
//从FactoryBean获取对象实例,这句是关键代码
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
// 返回对象实例
return object;
}
@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
//可以看到就是从factoryBeanObjectCache里面取已经缓存的,这样第二次再去获取的时候不用再次创建
return this.factoryBeanObjectCache.get(beanName);
}
让我们来看一下FactoryBeanRegistrySupport#getObjectFromFactoryBean方法:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 1.如果是单例,并且已经存在于单例对象缓存中,什么意思?
//就是说FactoryBean你可以在类上标注为多实例的bean,那么在多次获取FactoryBean的时候
//实际就是多次调用FactoryBean的getObject方法,如果是单实例的,则进行缓存起来,只创建一次
if (factory.isSingleton() && containsSingleton(beanName)) {
//2.加锁进行操作
synchronized (getSingletonMutex()) {
// 3.从FactoryBean创建的单例对象的缓存中获取该bean实例
//关于这个factoryBeanObjectCache上面我们已经介绍过了
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 4.调用FactoryBean的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);
// 5.如果该beanName已经在缓存中存在,则将object替换成缓存中的
if (alreadyThere != null) {
object = alreadyThere;
}
else {
//6.判断需要做后置处理,shouldPostProcess传过来的是!synthetic,即为true,不是合成的
//如果是合成的,就不需要做后置处理的。为什么?原因是这个后置处理就是判断是否需要对类进行AOP增强的
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
// 7.对bean实例进行后置处理,执行所有已注册的BeanPostProcessor的postProcessAfterInitialization方法
//此方法会进行AOP代理增强,所以我们在写AOP增强的时候,不只是会增强FactoryBean本身,还会增强FactoryBean所包裹的对象
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)) {
// 8.将beanName和object放到factoryBeanObjectCache缓存中
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
// 9.返回object对象实例
return object;
}
}
else {
// 10.调用FactoryBean的getObject方法获取对象实例
//可以看出来,如果是多实例的,那么每次是直接创建的
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
// 11.对bean实例进行后置处理,执行所有已注册的BeanPostProcessor的postProcessAfterInitialization方法
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
// 12.返回object对象实例
return object;
}
}
上述代码中的4会调用FactoryBean的getObject方法获取对象实例
上述代码中的7会对bean实例进行后置处理
代码如下:
FactoryBeanRegistrySupport#doGetObjectFromFactoryBean方法
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
// 1.调用FactoryBean的getObject方法获取bean对象实例
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
// 1.1 带有权限验证的
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 1.2 不带权限,factory.getObject就会最终执行我们实现了FactoryBean的方法
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.
// 2.getObject返回的是空值,并且该FactoryBean正在初始化中,则直接抛异常,不接受一个尚未完全初始化的FactoryBean的getObject返回的空值
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
// 3.返回创建好的bean对象实例
return object;
}
很简单的方法,就是直接调用 FactoryBean 的 getObject 方法来获取到对象实例。
调用 FactoryBeanRegistrySupport#postProcessObjectFromFactoryBean方法,主要是对bean进行后置后置增强的。
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 1.遍历所有注册的BeanPostProcessor实现类,调用postProcessAfterInitialization方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 2.在bean初始化后,调用postProcessAfterInitialization方法
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
// 3.如果返回null,则不会调用后续的BeanPostProcessors
return result;
}
}
return result;
}
总结:
1. 在取FactoryBean包裹的对象时(也就是不加&),先对名字进行转换,获取真正的beanName,然后从singletonObjects中取出bean实例,判断这个bea是否是否为FactoryBean类型的,如果是的话,在判断是单实例还是多实例的,如果是多实例的,则直接调用FactoryBean的getObject方法,如果单实例的,则先从factoryBeanObjectCache缓存中去拿,没有的话则进行创建,创建完成后,会判断这个FactoryBean的bd是不是合成,如果不是则执行BeanPostProcessor后置处理器的postProcessAfterInitialization进行增强(如果需要增强的话)。
2.FactoryBean包裹的对象是天然懒加载的,如果是单例的,则会在第一个调用getBean的时候创建,然后放到缓存中