Spring 扩展点系列:
其实,Spring 中还有一个很常用的扩展点 –FactoryBean。
传统的 Spring 容器加载一个 bean 的整个过程,都是由 Spring 控制的,换句话说,开发者除了设置Bean相关属性之外,是没有太多的自主权的。FactoryBean 改变了这一点,开发者可以个性化地定制自己想要实例化出来的 Bean,方法就是实现 FactoryBean 接口。
一般情况下,我们有两种方式我去注册 bean,applicationContext.xml 中的 <bean> 标签或者 JavaConfig 的 @Bean 注解。但是在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。
Spring 为此提供了一个org.springframework.bean.factory.FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 bean 的逻辑。我们需要做的就是把这个 factoryBean 注册到 IOC 容器中,当调用 getBean(factoryBean.class) 时获取 bean 得到的就是 factoryBean#getObject() 方法中创建的实例。
// 工厂 Bean,用于产生其他对象
public interface FactoryBean<T> {
// 获取容器管理的对象实例
@Nullable
T getObject() throws Exception;
// 获取 Bean 工厂创建的对象的类型
@Nullable
Class<?> getObjectType();
// Bean 工厂创建的对象是否是单态模式,如果是单态模式,则整个容器中只有一个实例对象,每次请求都返回同一个实例对象
default boolean isSingleton() {
return true;
}
}
FactoryBean 通常是用来创建比较复杂的 bean,一般的 bean 直接用xml配置即可,但如果一个 bean 的创建过程中涉及到很多其他的 bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用 FactoryBean。
下面来看一个示例…
1)创建一个工厂,实现 FactoryBean
public class TestFactoryBean implements FactoryBean {
private int listType;
public void setListType(int listType) {
this.listType = listType;
}
@Override
public Object getObject() throws Exception {
if (listType == 1) {
return new ArrayList();
} else if (listType == 2) {
return new LinkedList();
} else {
return new CopyOnWriteArrayList();
}
}
@Override
public Class<?> getObjectType() {
return List.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
2)配置 applicationContext.xml
<bean id="factoryBean" class="com.xupt.yzh.pkg_04.TestFactoryBean">
<!-- value=2 按照上面逻辑是返回LinkedList-->
<property name="listType" value="1"></property>
</bean>
3)测试代码:
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Class<?> factoryBean = context.getBean("factoryBean").getClass();
System.out.println(factoryBean);
}
}
结果如下:
可以看到最后得到的并不是 FactoryBean 本身,而是根据 FactoryBean#getObject() 的逻辑动态控制生成对象,所以我们可以灵活地操控Bean的生成,这就是FactoryBean的作用。
PS:关于 FactoryBean 的原理分析可以参考这篇文章…








还没有评论,来说两句吧...