Spring中FactoryBean源码分析(最详细)

        这篇文章我们来分析一下从容器中拿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的时候创建,然后放到缓存中

发布了225 篇原创文章 · 获赞 30 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_35634181/article/details/104507465