Spring源码分析(十二)FactoryBean的使用
摘要:本文结合《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的使用的更多相关文章
- spring源码分析系列 (8) FactoryBean工厂类机制
更多文章点击--spring源码分析系列 1.FactoryBean设计目的以及使用 2.FactoryBean工厂类机制运行机制分析 1.FactoryBean设计目的以及使用 FactoryBea ...
- Spring源码分析(二十四)初始化非延迟加载单例
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 完成BeanFactory的初始化工作,其中包括ConversionS ...
- Spring源码分析(二十五)finishRefresh
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在 Spring 中还提供了 Lifecycle 接口, Lifecy ...
- Spring源码分析(二十二)功能扩展
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.增加SPEL语言的支持 二.增加属性注册编辑器 1. 使用自 ...
- Spring源码分析(二十)准备环境
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. prepareRefresh函数主要是做些准备工作,例如对系统属性及环 ...
- Spring源码分析(二十三)BeanFactory的后处理
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.激活注册的 BeanFactoryPostProcessor ...
- Spring源码分析(二十一)加载BeanFactory
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.定制化BeanFactory 二.加载BeanDefinit ...
- Spring源码分析(二)容器基本用法
摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在正式分析Spring源码之前,我们有必要先来回顾一下Spring中最简 ...
- ABP源码分析十二:本地化
本文逐个分析ABP中涉及到locaization的接口和类,以及相互之间的关系.本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单.另一个是语言对应得本地化资源(Locali ...
- [Abp 源码分析]十二、多租户体系与权限验证
0.简介 承接上篇文章我们会在这篇文章详细解说一下 Abp 是如何结合 IPermissionChecker 与 IFeatureChecker 来实现一个完整的多租户系统的权限校验的. 1.多租户的 ...
随机推荐
- Code Signal_练习题_shapeArea
A 1-interesting polygon is just a square with a side of length 1. An n-interesting polygon is obtain ...
- LOJ#6463 AK YOI 树分治+线段树合并
传送门 既然是树上路径统计问题,不难想到要使用树分治,这里以点分治为例 由点分治的性质,每层只需要考虑经过重心的路径 因为需要维护路径长度在一定范围内的最大权值和,所以要用一个数据结构维护一下到根节点 ...
- BZOJ4144: [AMPPZ2014]Petrol(最短路 最小生成树)
题意 题目链接 Sol 做的时候忘记写题解了 可以参考这位大爷 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- centos文件基本操作
centos彻底删除文件夹.文件命令(centos 新建.删除.移动.复制等命令: 1.新建文件夹 mkdir 文件名 新建一个名为test的文件夹在home下 view source1 mkdir ...
- 那些年我们对npm 和 cnpm 的误区
1. npm 和 cnpm 的区别 相信很多人都不太明白 npm 和 cnpm 到底是什么东东, 为啥在国内要用 淘宝镜像使用 cnpm, (1) 两者之间只是 node 中包管理器的不同哟, (2) ...
- CentOS7.4 + Hadoop2.7.5安装配置管理(伪分布式)
1. 规划 1.1. 机器列表 NameNode SecondaryNameNode DataNodes 192.168.1.80 192.168.1.80 192.168.1.80 1.2. ...
- 网络I/O模型--04非阻塞模式(解除accept()、 read()方法阻塞)的基础上加入多线程技术
由于应用程序级别并没有使用多线程技术,这就导致了应用程序只能一个一个地对Socket 套接字进行处理.这个 Socket 套接宇没有处理完,就没法处理下一个 Socket 套接字 .针对这个 问题还是 ...
- linux rabbitmq 安装
下载 在安装 erlang 时使用的是源码包21.0版本:接着下载 rabbitmq-server/3.7.7 的源码包,编译时报错,说 erlang 版本号不满足条件,erlang版本>=19 ...
- Android UI组件----用相对布局RelativeLayout做一个登陆界面
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...
- sql server单个字段列转行由,隔开
SELECT STUFF((SELECT ','+字段名 FROM 表名 for xml path('')),1,1,'')