Spring源码分析之FactoryBean

一、FactoryBean介绍

如果说一个bean的创建逻辑很复杂,按照传统的方式配置在<bean>中提供大量的配置信息,这种配置方式的灵活性是受限的 。这时,采用编码的方式会得到一个更加简单的方案。Spring为此提供了一个工厂类接口BeanFactory,用户可以通过实现该接口定制实例化bean的逻辑。
在这里插入图片描述

public interface FactoryBean<T> {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class<?> getObjectType();
	
	default boolean isSingleton() {
		return true;
	}
}

该接口中定义了3个方法。

  • isSingleton();
    返回由FactoryBean创建的bean实例的作用域是单例还是原型。默认为单例。
  • T getObject();
    返回由FactoryBean创建的bean实例,如果isSingleton的作用域为单例,会将该实例放到单例池中。
  • Class<?> getObjectType();
    返回由FactoryBean要创建bean的类型。

FactoryBean和其他普通bean一样,需要去定义并且交给Spring进行管理,会放到Spring容器中。当通过getBean(beanName,xxx.class)方法调用时,普通的bean会返回与其类型相同的bean对象。而FactoryBean返回的不是其本身,而是调用它的getObject()方法返回的对象,这里相当于FactoryBean.getObject()代理了getBean()方法。

@Component
public class MyFactoryBean implements FactoryBean {

	private String beanName;

	@Override
	public Object getObject() throws Exception {
		return new OrderService();
	}

	@Override
	public Class<?> getObjectType() {
		return OrderService.class;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}
}
public class OrderService {
	
}

测试结果:
在这里插入图片描述

1.由FactoryBean产生Bean的过程

	@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name);
	}
	@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 {

		// 1.对beanName进行转换 name如果是"&myFactoryBean",那么beanName就是"myFactoryBean"
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		//2. 从单例池中获取bean实例
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 2.1 取到单例,判断sharedInstance是不是FactoryBean,如果是FactoryBean,那么真正需要拿到的是getObject方法所返回的对象
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			//2.1 没有取到单例
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 原型bean正在创建中
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			// 2.1.2 获取bean工厂
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 当前BeanFactory中不存beanName对象的BeanDefinition,那么则从ParentBeanFactory中去获取
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				// 2.1.3 得到合并后的BeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 加载DependsOn的bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						// 判断beanName是不是也被dep依赖了,如果是,就是相互依赖
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// 存在在两个map中
						// 1. dependentBeanMap,key为dep, value是一个LinkedHashSet,表示dep被哪些bean依赖了
						// 2. dependenciesForBeanMap,key为beanName,value是一个LinkedHashSet,表示beanName依赖了哪些bean
						registerDependentBean(dep, beanName);
						try {
							// 先去生成所依赖的bean
							getBean(dep); //  getBean("xxx")
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}


				// 2.1.4 根据Scope去创建bean
				// Create bean instance.
				if (mbd.isSingleton()) {
					// 获取单例bean,如果获取不到则创建一个bean,并且放入单例池中
					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;
						}
					});
					// sharedInstance可能是一个FactoryBean,所以需要单独再去factoryBeanObjectCache中去获取对应的对象
					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(); // request, session
					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, () -> {
							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.
		// 3.根据beanName获取到的bean的类型是否和requiredType匹配,如果不配则进行类型转化
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

1.首先会去将带有& 前缀的name做一下转化(有多个&连续的也行),就是去掉&,并且缓存。

	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		// 如果beanName没有以&开头,则直接返回
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		// 如果beanName以&开头,截取&后的beanName,并且把截取前后的name存在transformedBeanNameCache中
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

2.根据beanName去单例池中获取bean( 获取不到就去创建bean), 再去判断是不是FactoryBean

	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.
		// 如果是&myFactoryBean,那么则直接返回单例池(SingletonObjects)中的对象
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		// 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 .
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		// 如果beanInstance是FactoryBean,并且name也不是以&开头
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			object = getCachedObjectForFactoryBean(beanName);
		}

		// 从factoryBeanObjectCache中没有拿到则进行创建
		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());
			// 调用getObject方法得到对象并放入factoryBeanObjectCache中
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

2.1 这里会去factoryBeanObjectCache里去拿,有就拿出来,没有的话返回null。通过FactoryBean创建的出来的单例bean会放到这个缓存里,当然第一次调用是取不到的。
在这里插入图片描述

2.2 拿不到就去从这个工厂类里创建,调用doGetObjectFromFactoryBean方法,其实就是调用这个FactoryBean.getOject()。再拿到返回bean之后调用了 postProcessObjectFromFactoryBean(object, beanName);方法完成初始化后的操作。

	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 {
								// 调用BeanPostProcessor执行初始化后的逻辑,主要就是进行AOP
								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;
		}
	}
	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 {
				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.
		// 如果调用getObject()方法返回的是null,那么则返回一个NullBean
		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;
	}

在这里插入图片描述
初始化后:
在这里插入图片描述

2.3 将由FactoryBean创建出来的bean放到工厂池当中,下一次在取的时候(如果是单例的话)就从工厂池去取。单例池放的是正常扫描出来的bean,而工厂池里放到不是FactoryBean,是由它调用getObject()创建出来的单例bean。
在这里插入图片描述
如果想到factoryBean本身,那么直需要给beanName加上前缀“&”,在getBean(“&myFactoryBean”)时候获取的就是factoryBean本身了。
在这里插入图片描述
在这里插入图片描述
Spring正常创建Bean的过程,请参见我的这篇博文:Spring中Bean的生命周期(上)

2.SmartFactoryBean

这是FactoryBean的一个子接口, 实现这个接口,可以选择是否立即初始化bean。

public interface SmartFactoryBean<T> extends FactoryBean<T> {

	default boolean isPrototype() {
		return false;
	}
	default boolean isEagerInit() {
		return false;
	}
@Component
public class MySmartFactoryBean implements SmartFactoryBean {

	@Override
	public Object getObject() throws Exception {
		return new OrderService();
	}

	@Override
	public Class<?> getObjectType() {
		return OrderService.class;
	}

	@Override
	public boolean isEagerInit() {
		return true;
	}
}

在这里插入图片描述

在这里插入图片描述
这是第一次调用getBean方法,发现工厂池里已经有bean了,是什么时候放进去的?那肯定是Spring实例化非懒加载的单例bean时,放进去的因为我指定了isEagerInit = true。

	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// 循环bd,实例化单例bean
		for (String beanName : beanNames) {
			// 对beanDefinition进行合并,基于合并后的BeanDefinition去创建bean,将子bd的属性一步步递归覆盖父bd的属性
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

			// 非抽象,单例,非懒加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

				// FactoryBean
				// 判断是不是一个FactoryBean
				if (isFactoryBean(beanName)) {
					//  根据&beanName创建一个MySmartFactoryBean的对象
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						// eager:急切的意思,立马初始化
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							// 根据beanName去创建bean
							getBean(beanName);
						}
					}
				}
				else {
					// 根据beanName去创建bean
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}
	if (isEagerInit) {
		// 根据beanName去创建bean
		getBean(beanName);
	}

这里发现Spring自己调用了一次getBean()方法,而且没有获取返回值,它只是想将FactoryBean.getObject()返回的对象放进工厂池里。刚才已经看过将FactoryBean创建的bean放入工厂池的方法了,这里就不在赘述。

总结由FactoryBean创建的bean的流程

Created with Raphaël 2.2.0 完成FactoryBean创建 isEagerInit=true ? getObject()实例化 初始化后 完成创建 当调用getBean(); yes no

二、FactoryBean的应用

根据官方文档的介绍Spring大概在50多处地方使用FactoryBean的方式来创建Bean。我举两个例子

1.SqlSessionFactory。

Spring整合Mybatis时用到org.mybatis.spring.SqlSessionFactoryBean这个类,来创建SqlSessionFactory。
看一类关系图
在这里插入图片描述
当使用getBean()方法获取SqlSessionFactory,就会去调用getObject()方式返回实例。

  @Override
  public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
      afterPropertiesSet();
    }

    return this.sqlSessionFactory;
  }

2.MapperFactoryBean

单独使用Mybatis的时候,调用数据库接口的方式是:

	private static void testMybatis() {
		SqlSession sqlSession = SQL_SESSION_FACTORY.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		List<User> users = userMapper.selectAll();
		System.out.println("testMybatis");
		System.out.println(Arrays.toString(users.toArray()));
	}

mybatis在获取映射的过程中根据配置信息为UserMapper类型动态创建了代理类。而Spring的创建方式是:

	private static void testMybatisSpring() {
		ApplicationContext context = new ClassPathXmlApplicationContext("mybatis/spring.xml");
		UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
		List<User> users = userMapper.selectAll();
		System.out.println("testMybatisSpring");
		System.out.println(Arrays.toString(users.toArray()));
	}

这里我可以猜想到是Spring在获取bean时对Mybatis获取mapper做了一次封装。跟进代码里看到。
在这里插入图片描述

在这里插入图片描述
在看一下类继承图。
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值