BeanFactory和FactoryBean接口的区别

Spring版本:5.1.3.RELEASE

BeanFactory接口:

	String FACTORY_BEAN_PREFIX = "&";
	Object getBean(String name) throws BeansException;
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
	boolean containsBean(String name);
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	String[] getAliases(String name);

是简单工厂模式的应用,根据传入的beanName实例化相应的实例。

JavaDoc翻译(使用Google翻译并加以润色,如有歧义欢迎指出)

用于访问Spring bean容器的根接口。 这是bean容器的基本客户端视图; 其他接口(如ListableBeanFactory和org.springframework.beans.factory.config.ConfigurableBeanFactory)可用于特定目的。

该接口被一些持有bean定义的对象实现,每个bean定义由一个字符串名称唯一标识。
根据bean定义,工厂将返回包含对象的独立实例(Prototype设计模式)或单个共享实例(Singleton设计模式的高级替代,其中实例是工厂范围中的单例)。

将返回哪种类型的实例取决于bean工厂配置:API是相同的。
从Spring 2.0开始,根据具体的应用程序上下文(例如Web环境中的“request”和“session”范围),可以使用更多的scope(范围)。

这种方法的重点是BeanFactory是应用组件的注册中心和集中的配置中心(例如,不再需要单个对象去读取属性文件)。
有关此方法的优点的讨论,请参见"Expert One-on-One J2EE Design and Development"的第4章和第11章。

请注意,依靠依赖注入(“push”配置)通过setter或构造函数来配置应用对象通常更好,而不是像BeanFactory查找一样的使用“pull”配置的任意方式。Spring的依赖注入功能是使用这个BeanFactory接口及其子接口实现的。

通常,BeanFactory将加载存储在配置源(例如XML文档)中的bean定义,并使用org.springframework.beans包来配置bean。尽管如此,一种简单地实现是直接在Java代码中返回Java对象。如何存储定义没有限制:LDAP,RDBMS,XML,属性文件等。鼓励实现支持bean之间的引用(依赖注入)。

与ListableBeanFactory中的方法相反,如果这是HierarchicalBeanFactory,则此接口中的所有操作也将检查父工厂。如果在此工厂实例中找不到bean,则会询问直接父工厂(从父类bean工厂中获取)。此工厂实例中的Bean应该在任何父工厂中覆盖同名的Bean。

Bean工厂实现应尽可能支持标准bean生命周期接口。 完整的初始化方法及其标准顺序是:

  1. BeanNameAware 接口的 setBeanName 方法
  2. BeanClassLoaderAware 接口的 setBeanClassLoader 方法
  3. BeanFactoryAware 接口的 setBeanFactory 方法
  4. EnvironmentAware 接口的 setEnvironment 方法
  5. EmbeddedValueResolverAware 接口的 setEmbeddedValueResolver 方法
  6. ResourceLoaderAware 接口的 setResourceLoader 方法 (仅适用于在应用程序上下文(Application Context)中运行时)
  7. ApplicationEventPublisherAware 接口的 setApplicationEventPublisher 方法 (仅适用于在应用程序上下文(Application Context)中运行时)
  8. MessageSourceAware 接口的 setMessageSource 方法 (仅适用于在应用程序上下文(Application Context)中运行时)
  9. ApplicationContextAware 接口的 setApplicationContext 方法 (仅适用于在应用程序上下文(Application Context)中运行时)
  10. ServletContextAware 接口的 setServletContext 方法 (仅适用于在应用程序上下文(Application Context)中运行时)
  11. 所有实现了BeanPostProcessor接口的类的 postProcessBeforeInitialization 方法
  12. InitializingBean 接口的 afterPropertiesSet 方法
  13. 自定义的init方法
  14. 所有实现了BeanPostProcessor接口的类的 postProcessAfterInitialization 方法

关闭Bean工厂时,应用以下生命周期方法:

  1. 所有实现了DestructionAwareBeanPostProcessor接口的类的 postProcessBeforeDestruction 方法
  2. DisposableBean 接口的 destroy 方法
  3. 自定义的destroy 方法

Spring Bean生命周期图:

Spring 4.3.17.RELEASE 源码的JavaDoc文档写的也是以上流程。跟其它网上的文章写的流程有出入,应该以官方文档为准。

FactoryBean接口:

	T getObject() throws Exception;
	Class<?> getObjectType();
	default boolean isSingleton() {
		return true;
	}

是工厂方法模式的应用,由子类实现相应的实例。

JavaDoc翻译(使用Google翻译并加以润色,如有歧义欢迎指出)

接口被BeanFactory中使用的对象所实现,这些对象本身就是单个对象的工厂。如果bean实现了这个接口,它将被用作暴露此对象的工厂,而不是直接将自己作为bean实例给暴露出来。

注意:实现此接口的bean不能用作普通bean。

FactoryBean是被定义成bean的形式,但是bean对象的引用(getObject()方法获得)始终是由它创建的。

FactoryBeans可以支持单例和原型,可以根据需要懒惰地创建对象,也可以在启动时急切地创建对象。
SmartFactoryBean接口允许公开更细粒度的行为元数据。

该接口在框架内部大量使用,例如用于AOP的 org.springframework.aop.framework.ProxyFactoryBean类 或 org.springframework.jndi.JndiObjectFactoryBean类。
它也可以用于定制组件;但是,这仅适用于基础架构代码。

FactoryBean是一个programatic contract (编程合约)。实现不应该依赖annotation-driven (注解驱动)的注入或其他反射设施。

getObjectType()和getObject()方法的调用可能在引导过程的早期发生,甚至在所有的(post-processor)后置处理器设置之前。
如果您需要访问其他bean,请实现 BeanFactoryAware 并以编程方式获取它们。

最后,FactoryBean对象参与包含BeanFactory的bean创建的同步。
除了FactoryBean本身(或类似)中的延迟初始化之外,通常不需要内部同步。

下面从源码层面深入分析二者区别:

查看 BeanFactory接口的抽象类 AbstractBeanFactory的getObjectForBeanInstance方法的实现:

    protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// bean的name如果以&开头,则是FactoryBean实例
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			// 验证是否是FactoryBean对象,不是则抛出异常
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}

		// 执行到此处,已经得到了bean实例,如果是普通的bean,或者是FacoryBean实例,直接返回.
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
		    // 从FactoryBeanObjectCache中获取由FactoryBean创建的bean对象
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// beanInstance强转为FactoryBean
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// 如果是单例,则缓存从FactoryBean获取的对象
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 最终调用FactoryBean实例的getObject方法获取bean实例
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

在getObjectFromFactoryBean方法实现中会调用doGetObjectFromFactoryBean方法:

   private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
				    // 调用FactoryBean的getObject方法来返回实例
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				......
			}
			else {
			    // 调用FactoryBean的getObject方法来返回实例
				object = factory.getObject();
			}
		}
	    ......
		return object;
	}

实现FactoryBean的类,在初始化放入容器后,通过BeanFactory的getBean方法调用时,会调用FactoryBean的getObject方法返回对应的bean实例对象,而不是像普通的bean一样直接返回bean实例.

BeanFactory的常量&的作用是在获取bean的时候直接返回FactoryBean的bean实例,而不是调用的getObject方法返回对应的bean实例.

以上,如有问题欢迎提出!

参考: https://blog.youkuaiyun.com/silk_bar/article/details/60967064

<think>嗯,用户想了解Spring中的BeanFactoryFactoryBean区别用法。我需要仔细分析这两个概念的不同点。首先,BeanFactory是IoC容器的基础接口,负责管理获取Bean实例。而FactoryBean本身是一个Bean,但它的作用是创建其他Bean。这点可能容易混淆,因为它们名字相似。 根据引用[1],BeanFactory是生产Bean的工厂,所有Bean都由它管理。而引用[2]提到FactoryBean是一个特殊的Bean,用于生成或修饰对象,类似工厂模式。需要区分两者的角色:一个是容器本身,另一个是容器中的特殊Bean。 用户可能需要具体的例子来理解它们的用法。比如BeanFactory通过getBean()方法获取Bean,而FactoryBean需要实现getObject()来返回目标Bean。引用[3]指出FactoryBean像是中间人,提供其他Bean。例如,ProxyFactoryBean生成代理对象。 还要注意它们的应用场景。BeanFactory是核心容器,而FactoryBean用于复杂对象的创建,如整合第三方库或动态代理。引用[4]总结了两者的功能差异,BeanFactory提供基础管理,FactoryBean允许自定义创建逻辑。 用户可能还关心如何在实际开发中使用它们。例如,配置FactoryBean时,实际获取的是getObject()返回的对象,而不是FactoryBean本身。需要强调这点,避免误解。 最后,总结区别时,分点说明类型、功能、使用方式应用场景会更清晰。确保回答结构符合用户要求,使用中文,行内公式正确,并生成相关问题。</think>### BeanFactoryFactoryBean区别及用法解析 #### 一、核心区别 1. **类型与角色** - **BeanFactory** 是 Spring 的 **IoC 容器核心接口**,用于管理获取 Bean 实例。所有 Spring Bean生命周期均由它控制[^1]。 - **FactoryBean** 是一个特殊的 **Bean 类型**,本身作为容器中的 Bean 存在,但其核心功能是 **生产其他 Bean 实例**(例如代理对象或复杂对象)[^2]。 2. **功能对比** | 特性 | BeanFactory | FactoryBean | |---------------------|------------------------------|---------------------------------| | 定位 | Spring 容器的根接口 | 用于生成复杂对象的特殊 Bean | | 直接作用 | 管理所有 Bean 的注册与依赖注入 | 自定义生成特定类型的 Bean | | 获取对象方式 | 通过 `getBean("beanName")` | 通过 `FactoryBean.getObject()` | | 典型实现类 | `DefaultListableBeanFactory` | `ProxyFactoryBean`, `SqlSessionFactoryBean` | #### 二、具体用法示例 1. **BeanFactory 的典型使用** ```java // 创建容器 BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取 Bean 实例 UserService userService = factory.getBean("userService", UserService.class); ``` 2. **FactoryBean 的实现** ```java public class MyFactoryBean implements FactoryBean<MyObject> { @Override public MyObject getObject() { return new MyObject(); // 自定义创建逻辑 } @Override public Class<?> getObjectType() { return MyObject.class; } @Override public boolean isSingleton() { return true; } } ``` XML 配置: ```xml <bean id="myFactoryBean" class="com.example.MyFactoryBean"/> ``` 实际获取时: ```java // 获取的是 MyObject 实例,而非 MyFactoryBean 本身 MyObject obj = context.getBean("myFactoryBean"); ``` #### 三、应用场景对比 - **BeanFactory** 的应用场景: - 基础容器的初始化与 Bean 管理 - 实现延迟加载(Lazy Initialization) - 多级容器架构中的父/子容器设计[^4] - **FactoryBean** 的典型场景: - 集成第三方库(如 MyBatis 的 `SqlSessionFactoryBean`) - 生成动态代理对象(AOP 场景) - 封装复杂对象构建过程(如连接池配置) #### 四、关键注意事项 1. **FactoryBean 的特殊获取** 若需要获取 `FactoryBean` 本身而非其生产的对象,需在 Bean 名称前加 `&` 符号: ```java FactoryBean<?> factoryBean = context.getBean("&myFactoryBean"); ``` 2. **设计模式映射** `BeanFactory` 体现 **工厂模式**(统一管理对象),`FactoryBean` 更接近 **抽象工厂模式**(生产系列化对象)[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值