FactoryBean的作用

Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean即FactoryBean。FactoryBean和普通Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象。创建出来的对象是否属于单例由isSingleton中的返回决定。

一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean。

在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口。

用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说,占有重要的地位,Spring自身就提供了70多个FactoryBean的实现。他们隐藏了实例化的一些复杂Bean的细节,给上层应用带来了便利。

以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。

FactoryBean接口定义

1
2
3
4
5
6
7
8
9
10

package org.springframework.beans.factory;

public interface FactoryBean<T> {
T getObject() throws Exception;

Class<?> getObjectType();

boolean isSingleton();
}

应用场景

FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。

很多开源项目在集成Spring 时都使用到FactoryBean,比如 MyBatis3 提供 mybatis-spring项目中的 org.mybatis.spring.SqlSessionFactoryBean

1
2
3
4
5
6
<!-- spring和MyBatis整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>