spring的FactoryBean
(以下内容翻译自spring/docs/3.2.18.RELEASE)
为具有工厂属性的对象实现FactoryBean接口。
FactoryBean接口是spring IoC 容器实例化逻辑的一点补充。
如果你有一个复杂的对象,更适合用java代码描述而不是xml,你可以创建自己的FactoryBean,
并在类中写复杂的实例化代码,然后把自定义的FactoryBean加入到spring容器中。
示例:
<bean id="myBean" class="com.dao.MyFactoryBean"></bean>
public class ComplexObj {
public Date date;
public ComplexObj() {
System.out.println("ComplexObj construtcor");
}
}
public class MyFactoryBean implements FactoryBean<ComplexObj> {
public MyFactoryBean() {
System.out.println("MyFactoryBean constructor");
}
@Override
public ComplexObj getObject() throws Exception {
ComplexObj obj = new ComplexObj();
obj.date = new Date();
return obj;
}
@Override
public Class<?> getObjectType() {
return ComplexObj.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
getBean("myBean"); //返回FactoryBean创建的对象
getBean("&myBean"); //返回FactoryBean对象自身
Object bean = appCtx.getBean("myBean");
System.out.println(bean);
Object bean2 = appCtx.getBean("&myBean");
System.out.println(bean2);
1. spring容器创建MyFactoryBean的调用栈,就是一个普通单例bean的创建过程:

2. 创建工厂产品的调用栈:

AbstractBeanFactory
// AbstractBeanFactory
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException { final String beanName = transformedBeanName(name);
Object bean; // Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//获取工厂的产品对象,走if分支
// sharedInstance是MyFactoryBean对象
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
...
} // Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
延伸:dubbo的ReferenceBean实现了FactoryBean接口,所以启动consumer的时候,只会创建一个FactoryBean,
并不会去创建invoker代理,只有在触发getBean("xxx")操作时,才会真正去创建invoker代理。
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean {}
spring的FactoryBean的更多相关文章
- 聊聊Spring的FactoryBean其实没那么难
前言 谈到Spring的FactoryBean,就会知道Spring中经典的面试题:FactoryBean和BeanFactory的区别.我们这里就简单概括下: . BeanFactory是接口,提供 ...
- Spring之FactoryBean
首先要分辨BeanFactory 与 FactoryBean的区别, 两个名字很像,所以容易搞混 BeanFactory: 以Factory结尾,表示它是一个工厂类,是用于管理Bean的一个工厂 Fa ...
- Spring错误——Spring 注解——factory-bean reference points back to the same bean definition
背景:学习Spring,在使用注解@Bean的name属性配置<bean>实例时,不能注册实例成功 报错 WARNING: Exception encountered during con ...
- Spring的FactoryBean使用
Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean.工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的g ...
- spring 之 factory-bean & factory-method
这两者常常是一起出现的,或者说他们经常是一起被使用的.但是其实是分为了两种情况: 1 同时使用factory-bean 和 factory-method 如果,我们在一个bean 元素上同时配置 fa ...
- Spring中FactoryBean与BeanFactory的区别
版本:spring-framework-4.1 一概述 BeanFactory 与 FactoryBean的区别, 两个名字很像,面试中也经常遇到,所以容易搞混,现从源码以及示例两方面来分析. 二.源 ...
- Spring中FactoryBean的作用和实现原理
BeanFactory与FactoryBean,相信很多刚翻看Spring源码的同学跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的.BeanFactory是Spring中Bean工厂的顶层接口, ...
- 【带你手撸Spring】没有哪个框架开发,能离开 Spring 的 FactoryBean!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老司机,你的砖怎么搬的那么快? 是有劲?是技巧?是后门?总之,那个老司机的代码总是可 ...
- Spring 通过FactoryBean配置Bean
1.实现FactoryBean接口 import org.springframework.beans.factory.FactoryBean; public class CarFactoryBean ...
随机推荐
- Linux系统安装telnet以及xinetd服务
Linux系统安装telnet以及xinetd服务 一.安装telnet 1.检测telnet-server的rpm包是否安装 # rpm -qa telnet-server 若无输入内容,则表示没有 ...
- Python3基础 tuple 创建空元组或者只有一个元素的元组 并 用乘法成倍扩充
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- windows下启动某程序提示缺失**.dll文件的处理方法
一.背景: 1.os : windows7 64bit 旗舰版 2.启动ftp服务端软件时提示缺失mfc100.dll文件 以上情形亲测有效 二.修复 2.1 从https://cn.dll-file ...
- SQL 收集
1.union CREATE TABLE dbo.#testTab ( Id int NOT NULL ) insert into #testTab values(); insert into #te ...
- JavaScript 各种验证收集
filter或者forEach函数,可能是因为你的浏览器还不够新,暂时不支持新标准的函数,你可以使用如下方式自己定义: if (!Array.prototype.forEach) { Array.pr ...
- 解决 Ubuntu 14.04 图形界面无法正常显示 问题
参考: ubuntu清除系统缓存的方法 apt-get(四) 每天一个linux命令(33):df 命令 Ubuntu server 12.10 /dev/sda1 disk full 解决 Ubun ...
- HDU 3046 Pleasant sheep and big wolf(最小割最大流+Dinic)
http://acm.hdu.edu.cn/showproblem.php?pid=3046 题意: 给出矩阵地图和羊和狼的位置,求至少需要建多少栅栏,使得狼不能到达羊. 思路:狼和羊不能到达,最小割 ...
- 机器学习-数据可视化神器matplotlib学习之路(二)
之前学习了matplotlib的一些基本画图方法(查看上一节),这次主要是学习在图中加一些文字和其其它有趣的东西. 先来个最简单的图 from matplotlib import pyplot as ...
- 学习mybatis-3 step by step 篇三
动态 SQL if choose (when, otherwise) trim (where, set) foreach 动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分.比如: ...
- python获取文件扩展名的方法
主要介绍了python获取文件扩展名的方法,涉及Python针对文件路径的相关操作技巧 import os.path def file_extension(path): ] print file_ex ...