0
点赞
收藏
分享

微信扫一扫

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


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接口及其实现类的作用​​

Spring Framework 源码阅读(三):认识FactoryBean_后端


​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​​如下图所示:

Spring Framework 源码阅读(三):认识FactoryBean_.net_02


关注这一行(​​!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;
}

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

​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​​如下图所示:

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

会调用​​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​​如下图所示:

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


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


举报

相关推荐

0 条评论