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.csdn.net/silk_bar/article/details/60967064

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值