栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Framework 源码阅读(三):认识FactoryBean

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Framework 源码阅读(三):认识FactoryBean

Spring framework 源码阅读(三):认识FactoryBean

FactoryBean和BeanFactory虽然从命名上看起来相似,但作用却大不相同,BeanFactory负责创建和管理Spring容器中的bean,为bean从初始化到销毁建立了一整套统一的流程,让使用者可以不需要关注复杂的流程,只需关注bean本身的逻辑。而FactoryBean可以提供自定义bean初始化流程的功能,因此FactoryBean可以用于创建一类bean。

FactoryBean
public interface FactoryBean {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class getObjectType();

	default boolean isSingleton() {
		return true;
	}
}
  • 如果一个bean实现了FactoryBean接口,那么该bean将作为某一类bean的工厂,而不是直接作为一个bean。
  • 实现FactoryBean接口的bean不能用作普通bean。FactoryBean是以bean定义的,但是bean引用的对象始终是getObject方法创建的对象。
  • FactoryBean(不是单指FactoryBean接口)可以支持单例和原型,并且可以根据需要以懒加载的形式创建对象,也可以在启动时立即创建对象。SmartFactoryBean接口允许更细粒度的行为元数据。
  • FactoryBean接口在Spring框架中大量使用,例如ProxyFactoryBean(AOP)或JndiObjectFactoryBean。它也可用于定制component。

SmartFactoryBean接口源码:

public interface SmartFactoryBean extends FactoryBean {

	default boolean isPrototype() {
		return false;
	}

	default boolean isEagerInit() {
		return false;
	}
}
创建module

先在Spring framework源码中增加一个application module,这在之前的博文中已经介绍过了,这里就不再赘述:

  • Spring framework 源码阅读(一):Aware接口及其实现类的作用


IMessageService接口:

package com.kaven.service;



public interface IMessageService {
	default String getMessage() {
		return "default message";
	}
}

MessageServiceImpl实现类:

package com.kaven.service.impl;

import com.kaven.service.IMessageService;



public class MessageServiceImpl implements IMessageService {

	public String message;

	public MessageServiceImpl(String message) {
		this.message = message;
	}

	@Override
	public String getMessage() {
		return message;
	}
}

MessageServiceFactoryBean类(实现FactoryBean接口):

package com.kaven.factory;

import com.kaven.service.IMessageService;
import com.kaven.service.impl.MessageServiceImpl;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;



@Component("myFactoryBean")
public class MessageServiceFactoryBean implements FactoryBean {
	@Override
	public IMessageService getObject() throws Exception {
		return new MessageServiceImpl("Hello Spring");
	}

	@Override
	public Class getObjectType() {
		return IMessageService.class;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}
}

Application启动类:

package com.kaven;

import com.kaven.factory.MessageServiceFactoryBean;
import com.kaven.service.IMessageService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.Arrays;



@ComponentScan({"com.kaven"})
public class Application {

	public static void main(String[] args) {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);

		IMessageService messageServiceBean = (IMessageService) applicationContext.getBean("myFactoryBean");
		System.out.println(messageServiceBean.getMessage());

		IMessageService messageServiceBean2 = (IMessageService) applicationContext.getBean("myFactoryBean");
		System.out.println("messageServiceBean == messageServiceBean2: " + (messageServiceBean == messageServiceBean2));

		MessageServiceFactoryBean messageServiceFactoryBean = (MessageServiceFactoryBean) applicationContext.getBean("&myFactoryBean");
		System.out.println("isSingleton: " + messageServiceFactoryBean.isSingleton());

		System.out.println(applicationContext.getBeanDefinitionCount());
		Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);
	}
}

运行输出:

> Task :application:Application.main()
Hello Spring
messageServiceBean == messageServiceBean2: false
isSingleton: false
6
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
application
myFactoryBean

很显然输出结果符合预期,通过FactoryBean的bean名称获取bean,只会获取该FactoryBean中getObject()方法返回的实例,也就是这里的MessageServiceImpl实例,如果想要获取FactoryBean本身的bean,需要在FactoryBean的bean名称前拼接一个&字符,在代码中已经有演示了。

想要了解为什么会创建下面这4个bean,可以阅读这篇博客:

  • Spring framework 源码阅读(二):BeanDefinition的作用
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
源码分析

现在开始分析为什么实现了FactoryBean接口,就可以自定义创建某一类bean的流程了,以及获取FactoryBean本身的bean,为什么要在FactoryBean的bean名称前拼接一个&字符。

自定义的bean,大部分会在DefaultListableBeanFactory类的preInstantiateSingletons方法中被开始创建(删除了部分代码):

	@Override
	public void preInstantiateSingletons() throws BeansException {
		List beanNames = new ArrayList<>(this.beanDefinitionNames);

		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean factory = (FactoryBean) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}
	}

Debug如下图所示:

关注这一行(!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()结果是true,这些在AbstractBeanDefinition抽象类中设置了默认值,博主在上一篇博客中进行了介绍,并且isFactoryBean方法也会返回true,因为它就是FactoryBean):

    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
	String FACTORY_BEAN_PREFIX = "&";

很显然beanName就是FactoryBean的bean名称,而FACTORY_BEAN_PREFIX + beanName就是&myFactoryBean,所以这里是获取FactoryBean本身的bean。

后面还会调用AbstractBeanFactory抽象类的getObjectForBeanInstance方法(删除了部分代码):

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		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;
		}

		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			FactoryBean factory = (FactoryBean) beanInstance;
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

getObjectForBeanInstance方法会进行判断选择分支,会有三个分支,如果是获取FactoryBean本身的bean(getObjectForBeanInstance方法中的beanInstance参数其实在前面的调用链中已经被创建,如上图所示的sharedInstance变量,这里就不详细介绍,不然显得太杂乱,博主会在以后的博客中详细介绍bean的创建流程和生命周期),就会进入第一个分支:

		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;
		}

BeanFactoryUtils抽象类的isFactoryDereference方法(就是判断name参数在不为null的情况下有没有&前缀):

	public static boolean isFactoryDereference(@Nullable String name) {
		return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
	}

因此第一个分支就是返回FactoryBean本身的bean。

第二个分支(beanInstance参数不是FactoryBean实例,就是返回跟factory不相关的bean):

		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

第三个分支(很显然是返回FactoryBean对应的那一类bean,下面会详细介绍):

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			FactoryBean factory = (FactoryBean) beanInstance;
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}

回到获取FactoryBean本身bean的preInstantiateSingletons方法中的这个部分:

					if (bean instanceof FactoryBean) {
						FactoryBean factory = (FactoryBean) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}

SmartFactoryBean接口的源码在上面已经展示过了,非常简单,就是继承了FactoryBean接口,并且增加了两个方法,比如上面出现的isEagerInit()方法,这些源码都是相互联系的,大家还是要亲自Debug体验一下。因此这里的isEagerInit变量是false,因为MessageServiceFactoryBean类实现的是FactoryBean接口,所以实现FactoryBean接口的MessageServiceFactoryBean类不会立即(懒加载)创建它对应的那一类bean(MessageServiceImpl实例)。如果实现SmartFactoryBean接口,并且让isEagerInit方法返回true,在创建FactoryBean本身的bean后,也会立即创建FactoryBean对应的那一类bean,大家可以动手试一试。

因此,在ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);这行代码结束后,FactoryBean本身的bean就已经在Spring容器中了,以便后续可以创建该FactoryBean对应的那一类bean。

之后通过FactoryBean的bean名称来获取bean,就是该FactoryBean对应的那一类bean(通过getObject方法返回的实例)。

IMessageService messageServiceBean = (IMessageService) applicationContext.getBean("myFactoryBean");

Bebug如下图所示:

会调用AbstractBeanFactory抽象类的getObjectForBeanInstance方法(删除了部分代码),并且factory参数就是之前创建好的FactoryBean本身的bean(上面说过这里的beanInstance参数就是FactoryBean本身的bean,并且已经在之前的调用链中被创建好了,这里只是强转为FactoryBean类型,方便后续调用getObject方法)。

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
			
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			FactoryBean factory = (FactoryBean) beanInstance;
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

重点在这一行:

object = getObjectFromFactoryBean(factory, beanName, !synthetic);

调用了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) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								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)) {
							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;
		}
	}

这里的factory.isSingleton()会返回false,因此会执行下面这一行:

Object object = doGetObjectFromFactoryBean(factory, beanName);

调用了FactoryBeanRegistrySupport抽象类的doGetObjectFromFactoryBean方法:

	private Object doGetObjectFromFactoryBean(FactoryBean factory, String beanName) throws BeanCreationException {
		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				object = factory.getObject();
			}
		}
		return object;
	}
 

最终会执行object = factory.getObject();,而factory参数就是之前创建好的FactoryBean本身的bean,因此会调用FactoryBean中的getObject方法,创建了与该FactoryBean对应的那一类bean。

Debug如下图所示:

阅读源码需要耐心,一步步进行Debug,每个人的理解不同,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号