一文给你讲清楚BeanFactory 和 FactoryBean 的关联与区别
本文分享自华为云社区 《BeanFactory 和 FactoryBean 的关联与区别》,作者:战斧。
一、概括性的回答
两者其实都是Spring提供的接口,如下
public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); }
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; Class<?> getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }
BeanFactory 就是我们常说的Spring容器,其内包含着大量的Bean,我们可以从BeanFactory 获取到想要的Bean,或者查询Bean的一些信息。
而FactoryBean则是众多Bean里的一种,只不过这种Bean是一种辅助Bean或者说中间人,它的作用是为你提供另一个/一些Bean。
两者一个比较形象的比喻就是BeanFactory就是一家工厂,我们可以通过提供物品名字,从工厂中得到各式各样的物品,比如桌椅板凳,键盘鼠标 等等。而除此之外,我们还能获取一种比较特殊的物品——生产线(FactoryBean),一般情况下,我们获取生产线当然不是为了它本身,而是为了利用生产线生产出产品,所以当你提供生产线的名字,得到的其实是生产线生产的产品。当然,如果你就是想取这个生产线本身,那你提供的名字就得是 “&” + 生产线名。
二、FactoryBean
FactoryBean示例
我们先来看一下FactoryBean的基础用法,简而言之就是实现FactoryBean接口,然后重写其中的getObject方法,如下:
public class ConfigLoaderFactoryBean implements FactoryBean<ConfigLoader> { private String configLocation; public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } @Override public ConfigLoader getObject() throws Exception { if (configLocation.startsWith("file:")) { LocalConfigLoader configLoader = new LocalConfigLoader(); configLoader.setFilePath(configLocation.substring(5)); return configLoader; } else if (configLocation.startsWith("http:")) { RemoteConfigLoader configLoader = new RemoteConfigLoader(); configLoader.setServerUrl(configLocation); return configLoader; } else { throw new IllegalArgumentException("Unsupported config location: " + configLocation); } } @Override public Class<?> getObjectType() { return ConfigLoader.class; } }
然后把这个factoryBean放入容器中,你可以采用xml或者@Bean等形式注入。
<bean id="configLoader" class="com.example.ConfigLoaderFactoryBean"> <property name="configLocation" value="http://example.com/config.json"/> </bean
FactoryBean的必要性
我们上面介绍过,FactoryBean其实相当于一个中间人,我们获取它,往往不是需要它本身,而是希望通过它获得另一个Bean,自然的我们会产生疑问,为什么要多此一举?如果我们通过它是为了获得另一个Bean,那么为什么不直接实例化另一个Bean然后放入Spring容器呢?比如在方法上使用@Bean注解。
这种想法无可厚非,主要是因为factoryBean接口的诞生更早,所以早期很多的结构采用了这种方式。后续有了@Bean注解以后,在方法上使用@Bean注解也能实现复杂Bean的创建了。
那是不是所有情况都能使用@Bean来替代factoryBean呢?比如我们想每次获取的Bean都是实时的,又比如我们需要一个计时器Bean,但你注入的Bean都被固定了,只有通过工厂,才能每次获取都能得到一个实时的新Bean。同样的,使用factoryBean还有一个懒加载的作用,对于某些复杂的Bean能在获取时再进行实例化。
三、BeanFactory
BeanFactory与ApplicationContext
提及BeanFactory,自然而然的我们会想到Spring的重要特性IOC,IOC要求有一个能管理所有Bean的管家,而管家需要一个盛放这些Bean的容器,这个容器就是BeanFactory。
尽管我们在日常项目中,使用的容器是具有更全功能的ApplicationContext,但ApplicationContext也是BeanFactory的子接口,其除了单纯的容器功能外,还有配置元信息,应用事件机制,资源管理等功能,所以我们可以说ApplicationContext是BeanFactory的增强版本。
BeanFactory的使用
在早期的spring项目中,我们经常会在代码中指定使用某种BeanFactory ,并且使用如下方式去加载资源。
//读取核心的配置文件 ClassPathResource resource = new ClassPathResource("MyContext.xml"); BeanFactory BeanFactory = new XmlBeanFactory(resource);
顾名思义XmlBeanFactory就是能够读取并解析xml资源,解析出各种Bean后存入自身,而在后期,springboot的大规模使用后,其内置的工厂可以解析xml、properties以及注解等多种配置来源。
当然,其实Spring本身就有相当的自动化程度,比如当我们在启动类上使用。
@ImportResource(location = {"classpath:MyContext.xml"})
它也能导入内容,并根据资源后缀是否为".groovy"判断是使用GroovyBeanDefinitionReader.class 还是 XmlBeanDefinitionReader.class,对资源解析完成后,把Bean定义注册进BeanFactory中。
四、总结
我们应当发现了:BeanFactory 和 FactoryBean 除了名字相似、都能包含一些Bean实例之外,其实没有什么相同的地方。前者是SpringIOC的核心,是存放一切Bean的容器;后者只不过是对复杂Bean的一种包装,比如我们常用的myBatis组件,针对各个mapper级接口生成的Bean实例,就是以FactoryBean的形式存在Spring容器中的。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
企业诊断屋:二手车交易平台APP如何用AB测试赋能业务
更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 2023年汽车行业新车市场低靡,由新车降价引发的车辆价格波动很快传导到二手车市场,二手车的交易也受到了冲击,收车验车更加谨慎,诸多二手交易平台想要保障平台的交易率也变得竞争激烈。二手车交易平台需要吸引各方平台上交易,既要有卖家又要有买家,各方的体验在平台上均需要保障良好,才能顺利完成交易,因此想要优化平台的流程以及各类功能成为非常的关键点。 本期火山引擎AB测试企业诊断屋,将剖析一个汽车二手交易平台,在开发了自己的APP之后如何不断优化满足消费者需求的企业案例,看二手车交易平台如何应用AB实验优化产品满足个性化需求、提升成单转化。企业诊断屋是由火山引擎Datatester测试推出的AB测试行业科普系列内容。 千行百业用AB,每个行业、每个职能、业务的每一环节,都有多种AB实验的应用场景;数据可以帮助企业优化业务效率,科学的AB实验可以帮助企业提升效益。 该二手车交易平台在业务发展中遇到了两个瓶颈问题:已注册却沉睡的用户过多,用户留存率不够理想,平台内二手车交易转化流程中用户终止率过高。 针对上述...
- 下一篇
ELT in ByteHouse 实践与展望
更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 谈到数据仓库, 一定离不开使用Extract-Transform-Load (ETL)或 Extract-Load-Transform (ELT)。 将来源不同、格式各异的数据提取到数据仓库中,并进行处理加工。 传统的数据转换过程一般采用Extract-Transform-Load (ETL)来将业务数据转换为适合数仓的数据模型,然而,这依赖于独立于数仓外的ETL系统,因而维护成本较高。现在,以火山引擎ByteHouse为例的云原生数据仓库,凭借其强大的计算能力、可扩展性,开始全面支持Extract-Load-Transform (ELT)的能力,从而使用户免于维护多套异构系统。具体而言,用户可以将数据导入后,通过自定义的SQL语句,在ByteHouse内部进行数据转换,而无需依赖独立的ETL系统及资源。 火山引擎ByteHouse是一款基于开源ClickHouse推出的云原生数据仓库,本篇文章将介绍ByteHouse团队如何在ClickHouse的基础上,构建并优化ELT能力,具体包括四部分:Byt...
相关文章
文章评论
共有0条评论来说两句吧...