spring提供了一个FactoryBean这样的一个接口,使得用户可以通过实现这个接口来定制实例化bean的逻辑。这种注册方式多用于spring整合第三方框架的时候。
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
示例:
import org.springframework.beans.factory.FactoryBean;
public class ColorFactory implements FactoryBean<Color> {
public Color getObject() throws Exception {
System.out.println("ColorFactory...getObject...");
return new Color();
}
public Class<?> getObjectType() {
return Color.class;
}
/**
* 是否单实例
* true:是单实例 容器中只有一个实例
* false:是多实例 调用的时候容器才创建
*
* @return
*/
public boolean isSingleton() {
return true;
}
}
在配置类中加载组件
@Configuration
public class AnnotationConfigure {
@Bean("colorFactory")
public ColorFactory colorFactory() {
return new ColorFactory();
}
}
测试类:
@Test
public void testColorFactory(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationConfigure.class);
Object object = applicationContext.getBean("colorFactory");
System.out.println("colorFactory==========="+object.getClass());
Object object2 = applicationContext.getBean("&colorFactory");
System.out.println("&colorFactory=========="+object2.getClass());
}
执行结果如下:
Connected to the target VM, address: '127.0.0.1:63748', transport: 'socket'
colorFactory===========class Color
&colorFactory==========class ColorFactory
Disconnected from the target VM, address: '127.0.0.1:63748', transport: 'socket'
Process finished with exit code
简单来说就是,实现FactoryBean接口的bean,spring会在使用getBean()获取该bean时,自动调用该bean的getObject()方法,所以返回的不是Factory这个bean,而是bean.getObejct()方法的返回值。
FactoryBean通常是用来创建比较复杂的bean,一般的bean直接用xml配置即可,但如果一个bean的创建过程涉及到其他的bean和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。
典型的例子mybatis3提供的mybatis-spring项目中,创建SqlSessionFactory
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private Resource[] mapperLocations;
private DataSource dataSource;
private TransactionFactory transactionFactory;
private Properties configurationProperties;
private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
private SqlSessionFactory sqlSessionFactory;
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
this.afterPropertiesSet();
}
return this.sqlSessionFactory;
}
}