摘要:本文结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码。若有描述错误之处,欢迎指正。

一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean。在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量 的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。 Spring 为此提供了一个org.springframework.beans.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。

FactoryBean接口对于Spring框架来说占有重要的地位,Spring自身就提供了70多个 FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。从Spring 3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式:

public interface FactoryBean<T> {

    @Nullable
T getObject() throws Exception; @Nullable
Class<?> getObjectType(); default boolean isSingleton() {
return true;
}
}

在该接口中还定义了以下3个方法:

T getObject() 返回由 FactoryBean 创建的 bean 实例,如果 isSingleton()返回 true,则该实例会放到Spring容器中单实例缓存池中
Class<?> getObjectType() 返回 FactoryBean 创建的 bean 类型
boolean isSingleton() 返回由FactoryBean创建的bean实例的作用域是singleton还是 prototype。

当配置文件中<bean>的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于 FactoiyBean#getObject()代理了 getBean()方法。例如:如果使用传统方式配置下面Car的<bean> 时,Car的每个属性分別对应一个<property>元素标签。

public class Car {
private int maxSpeed;
private String brand;
private double price;
// get/set 方法
)

如果用FactoryBean的方式实现就会灵活一些,下例通过逗号分割符的方式一次性地为Car 的所有属性指定配置值:

public class CarFactoryBean implements FactoryBean<Car> {

    private String carInfo;

    @Nullable
@Override
public Car getObject() throws Exception {
Car car = new Car();
String[] infos = carInfo.split(",");
car.setBrand(infos[0]);
car.setMaxSpeed(Integer.valueOf(infos[1]));
car.setPrice(Double.valueOf(infos[2]));
return car;
} @Nullable
@Override
public Class<?> getObjectType() {
return Car.class;
} @Override
public boolean isSingleton() {
return false;
} // 接受逗号分隔符设置属性信息
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}

有了这个CarFactoryBean后,就可以在配置文件中使用下面这种自定义的配置方式配置 Car Bean 了:

<bean id="car" class="org.cellphone.uc.CarFactoryBean" carInfo="超级跑车,400,2000000"/>

与调用 getBean("car")时, Spring 通过反射机制发现 CarFactoryBean 实现了 FactoryBean 的接口,这时Spring容器就调用接口方法CarFactoryBean#getObject()方法返回。如果希望获取 CarFactoryBean的实例,则需要在使用getBean(beanName)方法时在beanName前显示的加上 "&"前缀,例如 getBean(”&car")。

Spring源码分析(十二)FactoryBean的使用的更多相关文章

  1. spring源码分析系列 (8) FactoryBean工厂类机制

    更多文章点击--spring源码分析系列 1.FactoryBean设计目的以及使用 2.FactoryBean工厂类机制运行机制分析 1.FactoryBean设计目的以及使用 FactoryBea ...

  2. Spring源码分析(二十四)初始化非延迟加载单例

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 完成BeanFactory的初始化工作,其中包括ConversionS ...

  3. Spring源码分析(二十五)finishRefresh

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在 Spring 中还提供了 Lifecycle 接口, Lifecy ...

  4. Spring源码分析(二十二)功能扩展

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.增加SPEL语言的支持 二.增加属性注册编辑器 1. 使用自 ...

  5. Spring源码分析(二十)准备环境

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. prepareRefresh函数主要是做些准备工作,例如对系统属性及环 ...

  6. Spring源码分析(二十三)BeanFactory的后处理

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.激活注册的 BeanFactoryPostProcessor ...

  7. Spring源码分析(二十一)加载BeanFactory

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.定制化BeanFactory 二.加载BeanDefinit ...

  8. Spring源码分析(二)容器基本用法

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在正式分析Spring源码之前,我们有必要先来回顾一下Spring中最简 ...

  9. ABP源码分析十二:本地化

    本文逐个分析ABP中涉及到locaization的接口和类,以及相互之间的关系.本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单.另一个是语言对应得本地化资源(Locali ...

  10. [Abp 源码分析]十二、多租户体系与权限验证

    0.简介 承接上篇文章我们会在这篇文章详细解说一下 Abp 是如何结合 IPermissionChecker 与 IFeatureChecker 来实现一个完整的多租户系统的权限校验的. 1.多租户的 ...

随机推荐

  1. opencv3.2.0图像离散傅里叶变换

    源码: ##名称:离散傅里叶变换 ##平台:QT5.7.1+opencv3.2.0 ##日期:2017年12月13. /**** 新建QT控制台程序****/ #include <QCoreAp ...

  2. LK光流算法的三个假设

    在实际过程中采用 Lucas-Kanade 光流算法跟踪运动物体特征点的时候,一个很明显的特点是LK算法(包括其他光流算法)不能计算"大运动",加上金子塔的方法稍微好点. 这是什么 ...

  3. 附加到SQL2012的数据库就不能再附加到低于SQL2012的数据库版本

    附加到SQL2012的数据库就不能再附加到低于SQL2012的数据库版本 昨天我只是将数据库附加到SQL2012,然后各个数据库都做了收缩事务日志的操作 兼容级别这些都没有改 再附加回SQL2005的 ...

  4. mac 打开整个系统的隐藏文件

    打开:defaults write com.apple.finder AppleShowAllFiles -bool true 关闭:defaults write com.apple.finder A ...

  5. ssh终端常用快捷键

    ssh终端常用快捷键 快捷键 描述 Ctrl+a 光标移动到行首 Ctrl+e 光标移动到行尾 Ctrl+c 终止当前程序 Ctrl+d 删除光标前的字符,或者推出当前中断 Ctrl+l 清屏 Ctr ...

  6. 18c新特性的一些小结(from JimmyHe)

    Oracle 18c在2018-02-16 release出来的,还是秉承着Oracle的cloud first理念,18c现在cloud和Engineered Systems上推出,想在传统的机器上 ...

  7. AFNetworking 2.5.x 网络请求的封装

    AFNetworking 2.5.x 网络请求的封装 源码地址 https://github.com/YouXianMing/Networking 说明 1. 将block形式的请求转换成用代理来处理 ...

  8. openweathermap-免费的天气预报接口

    openweathermap-免费的天气预报接口 其官方网址为:http://www.openweathermap.org/api 静态截图: 具备以下的一些特点: 1. Current weathe ...

  9. [转]SQL Server 数据库定时自动备份

    前提:在使用下面的备份方式之前需要确保你的Sqlserver Agent服务启动,切设置为自动启动.否则当你服务器重启了但是Agent服务没有启动,那么自动备份任务就不会执行 (一)使用TSql代码自 ...

  10. mysql的表和数据类型

    一.查看当前数据库所有表 mysql> use db Database changed mysql> show tables; Empty set (0.00 sec) #表示db数据库下 ...