Spring FactoryBean 源码分析

一、FactoryBean的作用

Spring 中有两种 bean ,一种是普通 bean ,另外一种则是 FactoryBean. 普通 bean 返回的是指定类的一个实例对象,而 FactoryBean 则不同,它返回的对象不是某一个指定类的实例对象,而是该 FactoryBean 的 getObject() 方法所返回的对象,创建出来的对象是单例还是多例,由 FactoryBean 的 isSingleton() 方法来控制.

一般情况下, Spring 通过获取 bean 标签中配置的 class 属性的全类名,通过反射(Class.forName(String className)来创建 bean 对象,但是在某些情况下,有一些 bean 的实例化过程比较复杂,如果按照传统的方式,则需要在 <bean...> 标签中配置大量的信息,配置方式的灵活性是受限制的,这个时候通过获取配置然后编码的方式来实例化 bean,可能只会得到一个简单的方案,不能满足我们实际的需求,为了解决这个问题, Spring 为此提供了一个 org.springframework.bean.factory.FactoryBean 的工厂类接口,用户可以通过实现该接口,通过该接口实现类中的 getObject() 方法私人订制 bean 的实现逻辑,这样就大大的增加了灵活性.同时这样也可以隐藏实例化 bean 的一些复杂的细节,给上层的调用带来了便利.

二、FactoryBean的使用特点

实现了 FactoryBean 接口的 bean 如果通过配置的 id 去获取,获取到的是 FactoryBean 调用 getObject()方法返回的对象,而不是FactoryBean 本身,如果想要获取到 FactoryBean 本身,需要在 id前面加上一个 & 符号,例如:

applicationContext.getBean("&id")

三、FactoryBean 案例演示  

1、FactoryBean 接口的实现类

// 自定义类 Person 实现 FactoryBean 接口
public class Person implements FactoryBean<Mango> {
    @Override
    public Mango getObject() throws Exception {
        Mango mango = new Mango();
        mango.setName("mango");
        mango.setColor("yellow");
        mango.setColor("10.0");
        return mango;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
		// 返回值是 true,代表创建的 Mango 对象是单例的,反之为多例
        return true;
    }
}

2、spring 配置文件(classpath:spring-config/spring-ioc.xml 配置文件)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="person" class="com.xiaomaomao.entity.Person"></bean>
</beans>

3、测试类

public class SpringTest {
    public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("classpath:spring-config/spring-ioc.xml");
        // 获取到的是 FactoryBean 本身实例对象
        Object person01 =ioc.getBean("&person");
        // 获取到的是 FactoryBean 调用 getObject() 方法返回的对象
        Object person02 = ioc.getBean("person");
        Object person03 = ioc.getBean("person");

        // 输出 FactoryBean 本身实例对象
        System.out.println(person01);
        // 输出 FactoryBean 调用 getObject() 方法返回的对象
        System.out.println(person02);
        // 判断 FactoryBean 调用 getObject() 方法返回的对象是不是单例
        System.out.println(person02 == person03);
    }
}

4、测试结果

通过测试结果,我们可以得出以下结论:

(1)、getBean("&id") 获取到的是 FactoryBean 本身对象

(2)、getBean("id") 获取到的是 FactoryBean 调用 getObject() 方法返回的对象

(3)、isSingleton() 方法可以控制 FactoryBean 调用 getObject() 方法返回的对象是单例还是多例

四、FactoryBean 的实际应用

就拿 Mybatis 来说吧,我们也是通过注入一个 SqlSessionFactoryBean ,实际上使用的却是 SqlSessionFactoryBean 对象通过调用 getObject() 方法返回的 SqlSessionFactory 对象.

<!-- spring 和 MyBatis 整合,不需要 mybatis 的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource"/>
	<!-- 自动扫描 mapping.xml 文件 -->
	<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>

五、FactoryBean 源码解析

说到这里就简单说一下 FactoryBean 的初始化和获取 IOC 中的 bean 的过程吧

// DefaultListableBeanFactory 类中的方法,代码行号: 728
public void preInstantiateSingletons() throws BeansException {
	if (this.logger.isDebugEnabled()) {
		this.logger.debug("Pre-instantiating singletons in " + this);
	}

	// 这里的 this 代表的是 DefaultListableBeanFactory 
	// 这个类里面封装了 spring 配置文件中所有,bean 标签的配置信息
	List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

	// 触发所有非懒加载的单例 bean 的初始化动作
	for (String beanName : beanNames) {
		// 合并父 bean 的配置
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		// 非懒加载、非抽象的单例 bean
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			// 判断当前 bean 是否是 FactoryBean (我们配置的 person 这个 bean 由于实现了 FactoryBean 这个接口
			// 所以它属于 FactoryBean
			if (isFactoryBean(beanName)) {
				// FactoryBean 的初始化动作,这里的 FACTORY_BEAN_PREFIX 是一个前缀 & 
				final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
				boolean isEagerInit;
				if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
					isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
						@Override
						public Boolean run() {
							return ((SmartFactoryBean<?>) factory).isEagerInit();
						}
					}, getAccessControlContext());
				}
				else {
					isEagerInit = (factory instanceof SmartFactoryBean &&
							((SmartFactoryBean<?>) factory).isEagerInit());
				}
				if (isEagerInit) {
					getBean(beanName);
				}
			}
			else {
				// 普通 bean 的初始化
				getBean(beanName);
			}
		}
	}

    // 到这里为止,我们所说的非懒加载非抽象的所有 singleton bean 已经初始化完毕
	// 如果我们定义的 bean 实现了 SmartInitializingSingleton 这个接口,那么会在这里回调
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged(new PrivilegedAction<Object>() {
					@Override
					public Object run() {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}

由于我们在 Spring 的配置文件中配置的 bean 是一个 FactoryBean ,所以我们点进去 (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName) 这个方法看一下,这个方法的参数是 &person (person 这个是 id ,我们在配置文件中配置的,解析 XML 的时候,这个 id 就赋值给了我们这里的 beanName)

// AbstractBeanFactory 类中的方法,代码行号: 196
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}

 同时可以看一下下面几个重载的方法,这个几个方法是我们获取 IOC 容器中 bean 的一些方法,当然上面那个方法既可以初始化 bean,也可以获取 IOC 容器中的 bean 对象

// 获取 bean 的时候   ioc.getBean("person",Person.class)
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	return doGetBean(name, requiredType, null, false);
}
// 获取 bean 的时候   ioc.getBean("person","xiaomao")
public Object getBean(String name, Object... args) throws BeansException {
	return doGetBean(name, null, args, false);
}
// 获取 bean 的时候   ioc.getBean("person", Person.class,"xiaomao","xiaomaomao")
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
	return doGetBean(name, requiredType, args, false);
}

不管是初始化 bean 还是获取 IOC 容器中的 bean ,我们都最终会调用 doGetBean(....) 这个方法,只是不同的需求下传入的参数值不同而已.点进去这个方法,看看里面到底有什么

// AbstractBeanFactory 类中的方法,代码行号: 235
protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

	// 对于普通的 bean,不管是初始化 bean 还是获取 bean, beanName 的值是不会有变化的,自始至终都是一样
	// 而对于 FactoryBean 来说,初始化 bean 的时候,由于传进来的参数 name 是带有 & 符号的,例如 &person
	// 这里是想真正的获取到 FactoryBean 的 beanName ,所以会去掉 & 符号
	final String beanName = transformedBeanName(name);
	
	// 这个要关注一下,创建 bean 、获取 bean 的返回值
	Object bean;

	// 判断父容器中是否已经创建过了该单例 bean
	// 第一次初始化的时候,这里是没有创建过该单例 bean 的,所以值为 null
	// 如果是后面通过 getBean(...) 来获取的 bean 实例的时候,因为初始化已经创建了 bean ,所以这里就不会为 null
	Object sharedInstance = getSingleton(beanName);
	// 如果没有创建该 singleton bean ,并且传入的参数为 null ,那么执行获取 bean 的操作
	// 如果获取 bean 实例的时候,传入了 args 参数,因为已经创建过了该 bean 实例,所以 sharedInstance 不为 null 
	// 这个时候如果传入的 args 参数不为 null ,那么就不满足该条件,这里就不是 获取 bean 了,而是需要创建 bean
	// 例如: ioc.getBean("person","xiaomao") ,这种情况会跳到下面的 else 分支中,就不是获取 bean,而是创建 bean
	if (sharedInstance != null && args == null) {
		if (logger.isDebugEnabled()) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
						"' that is not fully initialized yet - a consequence of a circular reference");
			}
			else {
				logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
			}
		}
		
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
	
	// 执行创建 bean 的操作
	// 如果我们通过 getBean(beanName,args) 传入了 args 参数,那么我们就不是获取 bean 了,而是要创建 bean 
	else {
		// 如果已经创建了该 beanName 的 prototype ,那么抛出异常
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// 检查是否这个 BeanDefinition 对象已经存在父容器中了
		BeanFactory parentBeanFactory = getParentBeanFactory();
		// 如果自身容器中不存在,父容器中存在该 BeanDefiniton
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			// Not found -> check parent.
			String nameToLookup = originalBeanName(name);
			if (args != null) {
				// Delegation to parent with explicit args.
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
				// No args -> delegate to standard getBean method.
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}
		// 标记已经创建了这个 bean
		if (!typeCheckOnly) {
			markBeanAsCreated(beanName);
		}

		try {
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			// Guarantee initialization of beans that the current bean depends on.
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
				for (String dep : dependsOn) {
					if (isDependent(beanName, dep)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
					}
					registerDependentBean(dep, beanName);
					getBean(dep);
				}
			}

			// 创建 bean 实例对象
			if (mbd.isSingleton()) {
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					@Override
					public Object getObject() throws BeansException {
						try {
							// 创建 bean 对象,核心方法...(我们这里就不看了,还是蛮多的)
							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;
						}
					}
				});
				// 如果是普通 bean ,返回自身对象
				// 如果是 FactoryBean 返回自身对象,而不是调用 getObject() 方法返回的对象
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}

			else if (mbd.isPrototype()) {
				// It's a prototype -> create a new instance.
				Object prototypeInstance = null;
				try {
					beforePrototypeCreation(beanName);
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					afterPrototypeCreation(beanName);
				}
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}

			else {
				String scopeName = mbd.getScope();
				final Scope scope = this.scopes.get(scopeName);
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
				}
				try {
					Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						}
					});
					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				}
				catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName,
							"Scope '" + scopeName + "' is not active for the current thread; consider " +
							"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
							ex);
				}
			}
		}
		catch (BeansException ex) {
			cleanupAfterBeanCreationFailure(beanName);
			throw ex;
		}
	}

	// Check if required type matches the type of the actual bean instance.
	if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
		try {
			return getTypeConverter().convertIfNecessary(bean, requiredType);
		}
		catch (TypeMismatchException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to convert bean '" + name + "' to required type '" +
						ClassUtils.getQualifiedName(requiredType) + "'", ex);
			}
			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
		}
	}
	return (T) bean;
}

看一下这个方法,虽然比较长,我们只关心我们需要的部分,上面这个方法不管最后执行哪一个分支,最终都会调用 bean = getObjectForBeanInstance(...) 这个方法,点进去看吧.

// AbstractBeanFactory 类中的方法,代码行号: 1607
protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

	// 两个判断条件
	// BeanFactoryUtils.isFactoryDereference(name):判断 name 是否不为空,并且以 & 开头
	// beanInstance instanceof FactoryBean:当前 bean 是否是 FactoryBean 的实现类
	
	
	if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
		throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
	}

	// 初始化的时候,如果是 FactoryBean ,那么上述两个判断条件都是成立的,直接返回一个 beanInstance 对象
	// 获取对象的时候,如果通过 ioc.getBean("&person") 这种方式,那么也是直接返回一个 beanInstance 对象
	// 这里的 beanInstance 是我们在 AbstractBeanFactory 类中通过调用 createBean(beanName, mbd, args)
	// 方法创建的,它是一个 Person 类的对象,不是 FactoryBean 实现类调用 getObject() 方法生产的对象
	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}
	
	// 如果是已经初始化完毕了,去 IOC 容器中获取 bean 实例对象的时候
	// 如果通过 ioc.getBean("person") 获取 bean 实例对象,会执行如下代码
	Object object = null;
	if (mbd == null) {
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		// beanInstance 是 Person 对象,而 Person 又是实现了 FactoryBean 接口的
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
	
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		boolean synthetic = (mbd != null && mbd.isSynthetic());
		// 获取 FactoryBean 的核心方法....
		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	}
	return object;
}

从上面代码我们知道, ioc.get("&person") 获取到的是 Person 类对象,如果我们要获取 Person 对象调用 getObject() 方法生产的 Mango 对象,该如何获取呢?

找到 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) {
				// FactoryBean 调用 getObject() 方法生产的对象
				object = doGetObjectFromFactoryBean(factory, beanName);
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else {
					if (object != null && shouldPostProcess) {
						try {
							object = postProcessObjectFromFactoryBean(object, beanName);
						}
						catch (Throwable ex) {
							throw new BeanCreationException(beanName,
									"Post-processing of FactoryBean's singleton object failed", ex);
						}
					}
					this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
				}
			}
			return (object != NULL_OBJECT ? object : null);
		}
	}
	else {
		// FactoryBean 调用 getObject() 方法生产的对象
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (object != null && shouldPostProcess) {
			try {
				object = postProcessObjectFromFactoryBean(object, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
			}
		}
		return object;
	}
}

细节就不看了,有一点是很明显的,不管判断条件如何,都会进入到 doGetObjectFromFactoryBean(factory, beanName) 这个方法里面,继续点进去看

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(new PrivilegedExceptionAction<Object>() {
					@Override
					public Object run() throws Exception {
							return factory.getObject();
						}
					}, acc);
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			// 这里的 factory 就是 FactoryBean 实现类对象,我们这里就是 Person 类对象
			// 根据继承的关系,子类中实现了 getObject() 方法,那么实际调用的就是子类里的 getObject()方法
			// 也就是我们 Person 对象中的 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 && isSingletonCurrentlyInCreation(beanName)) {
		throw new BeanCurrentlyInCreationException(
				beanName, "FactoryBean which is currently in creation returned null from getObject");
	}
	// 将BeanFactory 实现类对象通过调用 getObject() 方法生产的对象返回出去.
	return object;
}

  

 

原文地址:https://www.cnblogs.com/xiaomaomao/p/13991529.html