FactoryBeanRegistrySupport 源码分析

FactoryBeanRegistrySupport 源码分析

说明

  1. 本文基于 jdk 8, spring-framework 5.2.x 编写。
  2. @author JellyfishMIX - github / blog.jellyfishmix.com
  3. LICENSE GPL-2.0

类层次

向上继承、实现关系:

image-20220917015401240

向上向下所属层次:

image-20220917015444747

类签名:

/**
 * Support base class for singleton registries which need to handle
 * {@link org.springframework.beans.factory.FactoryBean} instances,
 * integrated with {@link DefaultSingletonBeanRegistry}'s singleton management.
 *
 * FactoryBeanRegistrySupport 在 DefaultSingletonBeanRegistry 基础上,增加了对 FactoryBean 的支持
 *
 * <p>Serves as base class for {@link AbstractBeanFactory}.
 *
 * @author Juergen Hoeller
 * @since 2.5.1
 */
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry

概述

FactoryBeanRegistrySupport 在 DefaultSingletonBeanRegistry 基础上,增加了对 FactoryBean 的支持。

关键属性

	/**
	 * Cache of singleton objects created by FactoryBeans: FactoryBean name to object.
	 *
	 * 缓存 factoryBean 创建的 singleton 对象
	 */
	private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

getTypeForFactoryBean 方法

	/**
	 * Determine the type for the given FactoryBean.
	 *
	 * 获取指定 factoryBean 中实例化对象的类型
	 *
	 * @param factoryBean the FactoryBean instance to check
	 * @return the FactoryBean's object type,
	 * or {@code null} if the type cannot be determined yet
	 */
	@Nullable
	protected Class<?> getTypeForFactoryBean(FactoryBean<?> factoryBean) {
		try {
			// 此处是 JDK 的权限控制,主要是操作系统层面的权限。业务开发中很少用到。
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged(
						(PrivilegedAction<Class<?>>) factoryBean::getObjectType, getAccessControlContext());
			}
			else {
				return factoryBean.getObjectType();
			}
		}
		catch (Throwable ex) {
			// Thrown from the FactoryBean's getObjectType implementation.
			logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
					"that it should return null if the type of its object cannot be determined yet", ex);
			return null;
		}
	}

获取指定 factoryBean 中实例化对象的类型。

getCachedObjectForFactoryBean 方法

	/**
	 * Obtain an object to expose from the given FactoryBean, if available
	 * in cached form. Quick check for minimal synchronization.
	 *
	 * 从 factoryBeanObjectCache 缓存中,获取指定的 beanName 对象
	 *
	 * @param beanName the name of the bean
	 * @return the object obtained from the FactoryBean,
	 * or {@code null} if not available
	 */
	@Nullable
	protected Object getCachedObjectForFactoryBean(String beanName) {
		return this.factoryBeanObjectCache.get(beanName);
	}

从 factoryBeanObjectCache 缓存中,获取指定的 beanName 对象。

getObjectFromFactoryBean 方法

	/**
	 * Obtain an object to expose from the given FactoryBean.
	 *
	 * 从指定的 FactoryBean 中,获取 beanName 对应的实例对象。
	 * 根据 factoryBean 是否单例,有不同的处理逻辑。并且有前置后置回调函数的预留位置,使得 FactoryBeanRegistrySupport 可以执行子类的重写的回调函数。
	 *
	 * @param factory the FactoryBean instance
	 * @param beanName the name of the bean
	 * @param shouldPostProcess whether the bean is subject to post-processing
	 * @return the object obtained from the FactoryBean
	 * @throws BeanCreationException if FactoryBean object creation failed
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		// 判断 factoryBean 是否是单例模式,以及 DefaultSingletonBeanFactory 的一级缓存中是否有 beanName 对应的 singleton 实例
		if (factory.isSingleton() && containsSingleton(beanName)) {
			// 针对一级缓存加锁,full singleton lock
			synchronized (getSingletonMutex()) {
				/*
				 * object 对象用于承载返回结果实例对象
				 * 尝试从 factoryBeanObjectCache 缓存中,获取指定的 beanName 对象
				 */
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					// 如果缓存中没有,通过 factoryBean 获取对象
					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)
					// 再次尝试从 factoryBeanObjectCache 缓存中,获取指定的 beanName 对象
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						// factoryBeanObjectCache 缓存中获取到了,赋值给返回结果 object
						object = alreadyThere;
					}
					else {
						// 如果有后置回调方法
						if (shouldPostProcess) {
							// 如果实例正在创建中
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							// 调用 singleton 实例创建的前置回调方法
							beforeSingletonCreation(beanName);
							try {
								// 调用后置回调方法,子类可以重写后置回调方法
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								// 调用 singleton 实例创建的后置回调方法
								afterSingletonCreation(beanName);
							}
						}
						// 如果一级缓存中包含 beanName 对应的 singleton 实例
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				// 返回处理后得到的结果实例
				return object;
			}
		}
		else {
			// factoryBean 非单例模式或一级缓存中没有 beanName 对应的 singleton 实例
			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;
		}
	}

从指定的 FactoryBean 中,获取 beanName 对应的实例对象。

根据 factoryBean 是否单例,有不同的处理逻辑。并且有前置后置回调函数的预留位置,使得 FactoryBeanRegistrySupport 可以执行子类的重写的回调函数。

doGetObjectFromFactoryBean 方法

/**
	 * Obtain an object to expose from the given FactoryBean.
	 *
	 * 从指定的 FactoryBean 中,获取 beanName 对应的实例对象。真正在获取实例对象的方法。
	 *
	 * @param factory the FactoryBean instance
	 * @param beanName the name of the bean
	 * @return the object obtained from the FactoryBean
	 * @throws BeanCreationException if FactoryBean object creation failed
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
		// object 对象用于承载返回结果实例对象
		Object object;
		try {
			// 此处是 JDK 的权限控制,主要是操作系统层面的权限。业务开发中很少用到。
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				// 调用 factoryBean 获得实例
				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) {
			// 如果返回结果为 null 且 beanName 对应的实例正在创建中,则抛出异常
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			// 如果返回结果为 null,则创建一个空 Bean(NullBean) 赋值给返回结果
			object = new NullBean();
		}
		// 返回处理后得到的结果实例
		return object;
	}

从指定的 FactoryBean 中,获取 beanName 对应的实例对象。真正在获取实例对象的方法。

postProcessObjectFromFactoryBean 方法

	/**
	 * Post-process the given object that has been obtained from the FactoryBean.
	 * The resulting object will get exposed for bean references.
	 * <p>The default implementation simply returns the given object as-is.
	 * Subclasses may override this, for example, to apply post-processors.
	 *
	 * 后置回调方法,子类可以重写后置回调方法。
	 * 通过这样的回调函数预设,使得 FactoryBeanRegistrySupport 可以执行子类的重写的回调函数。
	 *
	 * @param object the object obtained from the FactoryBean.
	 * @param beanName the name of the bean
	 * @return the object to expose
	 * @throws org.springframework.beans.BeansException if any post-processing failed
	 */
	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
		return object;
	}

后置回调方法,子类可以重写后置回调方法。

通过这样的回调函数预设,使得 FactoryBeanRegistrySupport 可以执行子类的重写的回调函数。

getFactoryBean 方法

	/**
	 * Get a FactoryBean for the given bean if possible.
	 *
	 * 传入一个普通对象,如果该实例是 factoryBean 的实例,返回一个 factoryBean 实例。否则抛出异常。
	 *
	 * @param beanName the name of the bean
	 * @param beanInstance the corresponding bean instance
	 * @return the bean instance as FactoryBean
	 * @throws BeansException if the given bean cannot be exposed as a FactoryBean
	 */
	protected FactoryBean<?> getFactoryBean(String beanName, Object beanInstance) throws BeansException {
		if (!(beanInstance instanceof FactoryBean)) {
			throw new BeanCreationException(beanName,
					"Bean instance of type [" + beanInstance.getClass() + "] is not a FactoryBean");
		}
		return (FactoryBean<?>) beanInstance;
	}

传入一个普通对象,如果该实例是 factoryBean 的实例,返回一个 factoryBean 实例。否则抛出异常。

removeSingleton 方法

	/**
	 * Overridden to clear the FactoryBean object cache as well.
	 *
	 * 各级缓存中都根据 beanName 移除对应的 singleton。
	 * FactoryBeanRegistrySupport 除了移除父类 DefaultSingletonBeanRegistry 中的各级缓存,还需要移除 factoryBean 创建的 singleton 对象缓存。
	 */
	@Override
	protected void removeSingleton(String beanName) {
		synchronized (getSingletonMutex()) {
			super.removeSingleton(beanName);
			this.factoryBeanObjectCache.remove(beanName);
		}
	}

各级缓存中都根据 beanName 移除对应的 singleton。

FactoryBeanRegistrySupport 除了移除父类 DefaultSingletonBeanRegistry 中的各级缓存,还需要移除 factoryBean 创建的 singleton 对象缓存。

clearSingletonCache 方法

	/**
	 * Overridden to clear the FactoryBean object cache as well.
	 *
	 * 清空各级缓存中的元素。
	 * FactoryBeanRegistrySupport 除了清空父类 DefaultSingletonBeanRegistry 中的各级缓存,还需要清空 factoryBean 创建的 singleton 对象缓存。
	 */
	@Override
	protected void clearSingletonCache() {
		synchronized (getSingletonMutex()) {
			super.clearSingletonCache();
			this.factoryBeanObjectCache.clear();
		}
	}

清空各级缓存中的元素。

FactoryBeanRegistrySupport 除了清空父类 DefaultSingletonBeanRegistry 中的各级缓存,还需要清空 factoryBean 创建的 singleton 对象缓存。

<think>好的,我现在需要回答用户关于Spring框架中哪些地方使用了工厂方法模式或抽象工厂模式的问题。首先,我得回顾一下工厂方法模式和抽象工厂模式的定义和特点,然后结合Spring的具体实现来分析。 工厂方法模式通常涉及一个创建对象的接口,让子类决定实例化哪个类。而抽象工厂模式则是提供一个创建一系列相关或依赖对象的接口,无需指定具体类。这两种模式都属于创建型设计模式,用于解耦对象的创建和使用。 接下来,我需要回忆Spring框架中的核心组件,比如BeanFactory、ApplicationContext,以及具体的实现类如XmlBeanFactory、ClassPathXmlApplicationContext等。这些容器在管理Bean的生命周期时,是否用到了工厂模式? 首先,BeanFactory本身就是一个工厂接口,它定义了getBean方法,用于获取Bean实例。具体的实现类如DefaultListableBeanFactory负责实际的Bean创建。这里可能使用了工厂方法模式,因为BeanFactory的子类负责决定如何创建Bean。 然后,ApplicationContext作为BeanFactory的子接口,扩展了更多功能,比如国际化、事件传播等。ApplicationContext的实现类如ClassPathXmlApplicationContext在初始化时,会加载配置文件并创建Bean。这里的Bean创建过程可能涉及到工厂方法,因为不同的ApplicationContext实现可能有不同的创建逻辑。 另外,Spring中的FactoryBean接口允许用户自定义Bean的创建逻辑。例如,当配置一个FactoryBean的实现类时,Spring容器会调用其getObject()方法来获取Bean实例。这明显是工厂方法的应用,因为FactoryBean的实现类负责创建具体的对象。 还有,在Spring的配置中,使用@Bean注解的方法实际上也是一个工厂方法。当Java配置类中的方法被@Bean注解标记时,Spring会调用该方法来获取Bean实例,这符合工厂方法模式的定义。 关于抽象工厂模式,Spring中的BeanFactory可以视为一个抽象工厂,因为它定义了创建Bean的方法,而具体的实现类如DefaultListableBeanFactory和AnnotationConfigApplicationContext负责创建不同系列的Bean。不过,抽象工厂模式更强调创建多个相关或依赖的对象,而BeanFactory主要关注单个Bean的创建,可能更偏向工厂方法模式。但如果有多个相关的Bean需要一起创建,可能涉及到抽象工厂的思想。 此外,Spring Boot中的自动配置机制可能也使用了工厂模式。自动配置类根据类路径和环境条件决定创建哪些Bean,这可能涉及到工厂方法或抽象工厂,以确保相关配置的Bean被正确创建和组合。 总结一下,Spring中用到工厂方法模式的地方包括BeanFactory及其实现类、FactoryBean接口、@Bean注解方法等。而抽象工厂模式可能体现在需要创建多个相关Bean的情况下,例如不同配置环境下的Bean组。不过需要进一步验证这些点是否正确,可能需要查阅Spring的源码或文档来确认具体实现细节。</think>#### Spring框架中工厂模式的应用分析 --- ##### 一、工厂方法模式的应用 1. **`BeanFactory` 核心接口** - **定义**:`BeanFactory` 是Spring容器的根接口,提供`getBean()`等工厂方法。 - **实现**:`DefaultListableBeanFactory` 是其核心实现类,通过`createBean()`方法完成Bean的实例化、依赖注入等操作。 - **代码示例**: ```java BeanFactory factory = new DefaultListableBeanFactory(); MyBean bean = factory.getBean(MyBean.class); ``` 2. **`FactoryBean` 接口** - **作用**:允许自定义复杂对象的创建逻辑(如代理对象、第三方库实例)。 - **实现**:用户实现`FactoryBean`接口的`getObject()`方法,Spring容器调用该方法获取Bean实例。 - **示例**: ```java public class MyFactoryBean implements FactoryBean<MyObject> { @Override public MyObject getObject() { return new MyObject(); // 自定义创建逻辑 } } ``` 3. **`@Bean` 注解方法** - **应用场景**:在Java配置类中,通过`@Bean`标注的方法等价于工厂方法。 - **示例**: ```java @Configuration public class AppConfig { @Bean public DataSource dataSource() { return new HikariDataSource(); // 工厂方法返回具体实例 } } ``` --- ##### 二、抽象工厂模式的应用 1. **`ApplicationContext` 多场景适配** - **实现类**:`ClassPathXmlApplicationContext`(XML配置)、`AnnotationConfigApplicationContext`(注解配置)等不同实现类,对应不同配置方式的**产品族**(如Bean定义解析器、资源加载器)。 - **特点**:同一应用上下文中,所有Bean的创建逻辑保持一致性(如注解驱动或XML驱动)。 2. **环境隔离(Profile)** - **功能**:通过`@Profile`注解定义不同环境(如`dev`/`prod`)的Bean组,Spring根据激活的Profile选择对应的**具体工厂**。 - **示例**: ```java @Configuration @Profile("dev") public class DevConfig { @Bean public DataSource devDataSource() { return new EmbeddedDatabaseBuilder().build(); // 开发环境数据源 } } ``` 3. **`BeanDefinitionRegistryPostProcessor`** - **作用**:允许在容器启动时动态注册Bean定义,本质上是通过抽象工厂模式生成不同**Bean定义族**(如AOP代理类、事务管理器等)。 --- ##### 三、典型场景对比 | **场景** | **模式类型** | **关键实现** | |---------------------------|--------------------|-----------------------------------------------------------------------------| | Bean实例化 | 工厂方法 | `BeanFactory.getBean()` -> `AbstractBeanFactory.createBean()` | | 自定义对象创建 | 工厂方法 | `FactoryBean.getObject()` | | 多环境配置切换 | 抽象工厂 | `ApplicationContext` + `@Profile` 选择不同配置族 | | 动态代理生成 | 抽象工厂 | `ProxyFactoryBean` 创建AOP代理对象族(JDK/CGLIB) | --- ##### 四、源码关键逻辑解析 1. **`AbstractBeanFactory#doGetBean`** - **逻辑**:通过`getBean()`方法调用`createBean()`,最终由`BeanFactory`实现类完成对象创建。 - **代码片段**: ```java protected <T> T doGetBean(...) { // 1. 检查缓存 // 2. 创建Bean实例(调用工厂方法) Object beanInstance = createBean(beanName, mbd, args); return adaptBeanInstance(beanName, beanInstance, requiredType); } ``` 2. **`FactoryBean` 的加载流程** - **步骤**: 1. 容器检测到Bean是`FactoryBean`类型。 2. 调用`getObject()`方法获取真实对象。 - **源码入口**:`FactoryBeanRegistrySupport#getObjectFromFactoryBean` --- ##### 五、总结 - **工厂方法模式**:贯穿Spring核心容器(如`BeanFactory`、`@Bean`方法),解决**单一对象**的灵活创建问题。 - **抽象工厂模式**:体现在多环境配置、多组件适配场景,保证**系列对象**的兼容性。 - **设计价值**:通过解耦对象创建与使用,Spring实现了配置与代码分离、扩展性增强等核心优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JellyfishMIX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值