Spring Framework 源码阅读(三):认识FactoryBean
FactoryBean
和BeanFactory
虽然从命名上看起来相似,但作用却大不相同,BeanFactory
负责创建和管理Spring
容器中的bean
,为bean
从初始化到销毁建立了一整套统一的流程,让使用者可以不需要关注复杂的流程,只需关注bean
本身的逻辑。而FactoryBean
可以提供自定义bean
初始化流程的功能,因此FactoryBean
可以用于创建一类bean
。
FactoryBean
public interface FactoryBean<T> {
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<T> extends FactoryBean<T> {
default boolean isPrototype() {
return false;
}
default boolean isEagerInit() {
return false;
}
}
创建module
先在Spring Framework
源码中增加一个application module
,这在之前的博文中已经介绍过了,这里就不再赘述:
- Spring Framework 源码阅读(一):Aware接口及其实现类的作用
IMessageService
接口:
package com.kaven.service;
/**
* @Author: ITKaven
* @Date: 2021/09/25 14:04
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
public interface IMessageService {
default String getMessage() {
return "default message";
}
}
MessageServiceImpl
实现类:
package com.kaven.service.impl;
import com.kaven.service.IMessageService;
/**
* @Author: ITKaven
* @Date: 2021/09/25 14:05
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
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;
/**
* @Author: ITKaven
* @Date: 2021/10/28 20:01
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@Component("myFactoryBean")
public class MessageServiceFactoryBean implements FactoryBean<IMessageService> {
@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;
/**
* @Author: ITKaven
* @Date: 2021/09/25 13:54
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@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<String> 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<Boolean>) ((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<Boolean>) ((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<Object>) 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
,每个人的理解不同,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。