[注]本文转译自http://geekabyte.blogspot.com/2014/11/difference-between-beanfactory-and.html
本文主旨是阐明Spring框架中的FactoryBean和BeanFactory两个接口的区别,但首先来扯一下Spring的大致构成。
Spring涉及的东西很多,但就其核心那要数依赖注入了,依赖注入容器由以下四个组件构成:
1.org.springframework.core,这个包里是基本功能实现,如异常、版本探测等;
2.org.springframework.beans,这里是管理bean的一些接口和类,FactoryBean就在这个包下;
3.org.springframework.context,这个包构建于org.springframework.beans之上,ApplicationContext就实现了BeanFactory;
4.org.springframework.expression,这个包提供了Spring的表达式语言;
Springframework的核心架构是这样的,
IoC的容器就实现在Spring-Beans包里,支持Spring-Core的功能,Spring-Context是基于Spring-Core和Spring-Beans来扩展的,所以引入Spring-Context包就自然地引入了Spring-Core和Spring-Beans的IoC容器。
org.springframework.beans管理着bean的创建,注入等,FactoryBean接口就在这个包中,而BeanFactory接口在子包org.springframework.beans.factory中。
转入主题,FactoryBean和BeanFactory有什么区别呢?
实际上这两个接口有完全不同的目的,FactoryBean这个接口是当你实现工厂接口时,期望把FactoryBean创建的对象托管给spring管理;而BeanFacrory接口是一个工厂,代表的是IoC容器,它的扩展实现(如,ClassPathXmlApplicationContext)管理着我们创建的beans,并提供了多种途径来获取我们想要的具名的bean。大多数情况下,我们都不会直接去实现BeanFactory这个接口,除非你想要扩展Spring容器的核心功能集,但是如果想要让spring帮助管理由factory创建的对象时,我们就需要FactoryBean了。
简言之,BeanFactory可视为IoC容器,FactoryBean是一个工厂类,它创建的对象将被注册到容器中从而得到IoC容器的管理。
现用两个简单的代码片段来辅助解释
1.FactoryBean
先来看一下这个接口的定义,3.0后支持泛型,
package org.springframework.beans.factory;public interface FactoryBean{ T getObject() throws Exception; Class getObjectType(); boolean isSingleton();}
再来看一片配置文件片断,
create-drop org.hibernate.dialect.MySQL5Dialect
如果去读LocalContainerEntityManagerFactoryBean的源码,你会发现这个类并没有jpaVendorAdapter这些属性,那为什么会出现这些属性呢?
这是因为LocalContainerEntityManagerFactoryBean实现了FactoryBean接口,spring不会返回LocalContainerEntityManagerFactoryBean本身,而是通过#getObject返回了EntityManagerFactory这个类型的一个对象,才有我们看到的那么多属性可配置。
2.BeanFactory
先看下这个接口的代码,
package org.springframework.beans.factory;import org.springframework.beans.BeansException;public interface BeanFactory { /** * Used to dereference a { @link FactoryBean} instance and distinguish it from * beans created by the FactoryBean. For example, if the bean named *myJndiObject
is a FactoryBean, getting&myJndiObject
* will return the factory, not the instance returned by the factory. */ String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException;T getBean(String name, Class requiredType) throws BeansException; T getBean(Class requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException; Class getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name);}
注意,标红的
String FACTORY_BEAN_PREFIX = "&";
这个属性是专门为FactoryBean设置的,正如1中说到,FactoryBean的实现类默认返回的对象是#getObject的类弄,如果我们就要返回FactoryBean的实现本身的实例呢?于是,就要用到这个前缀&了,
ApplicationContext context=new ClassPathXmlApplicationContext("classpath:foo-config.xml");FooFactoryBean ffb=context.getBean("&fooFactoryBean"); //从这里可以看出BeanFactory和FactoryBean的关系,spring Bean工厂BeanFactory管理着包括FactoryBean实例的所有bean,而FactoryBean又是特殊的,厂长还专门给这个bean设置了标记&.
接着说这个ClassPathXmlApplicationContext实现了ApplicationContext,而ApplicationContext实现了BeanFactory:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {