当前位置: 首页 > article >正文

FactoryBean接口的原理与使用场景

下图中的TestFactoryBean接口是类型是FactoryBean,用以下两行代码进行测试会发现

1、ctx.getBean("TestFactoryBean");返回的类型就是OneFactoryBean,也就是会调用到TestFactoryBean中getObject()方法;

2、如果调用ctx.getBean("&TestFactoryBean")方法,那么就会将容器中的TestFactoryBean实例给返回。

以上两个demo就是FactoryBean特别的地方,具体源码是怎样处理的还是要去看bean的实例化过程。首先可以看到,当我们传进来的beanName带有&符号时,程序会做一个截取的过程,例如参数name传进来的是&TestFactoryBean,截取后变量beanName就是TestFactoryBean。

来到实例化的核心流程可以看到对TestFactoryBean的创建流程其实是跟普通的bean实没什么区别的,但是下面有一段关键的代码去处理getObject方法,其实就是处理FactoryBean类型的入口

来到这个方法,注意这里的入参sharedInstance就是刚创建好的TestFactoryBean,name就是我们在外面传进来的,可能是&TestFactoryBean,也可能是TestFactoryBean;但是beanName就是截取掉&之后的,肯定是不带有&;

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);进来会判断我们传进来的name是不是带有&符号的,如果带有则就会把TestFactoryBean这个实例返回。

如果传进来的不带有&符号,就会先去从缓存中去获取,可以看到FactoryBean类型getObject返回的实例是从factoryBeanObjectCache缓存中获取的,跟普通的bean所在的容器是不同的。

第一次的获取的时候,容器中肯定是没有的,此时就会执行到下面的object = getObjectFromFactoryBean(factory, beanName, !synthetic)方法,这里就会去调用FactoryBean的getObject方法。

获取到getObject方法返回的实例后,会去做两个事情,

1、执行beanPostProcessor的初始化方法

2、将获取到的对象放入到缓存中factoryBeanObjectCache中

这里是去对getObject返回的实例做初始化操作,执行beanPostProcessor的埋点方法,放入到缓存之后FactoryBean的处理流程就结束了。

当第二次再去获取FactoryBean类型的时候,这个时候就会直接从factoryBeanObjectCache获取到了。

FactoryBean通过提供灵活的Bean创建机制、延迟加载、代理对象创建、复杂配置封装等功能,极大地增强了Spring框架的灵活性和可扩展性。

1、定制实例化逻辑‌:FactoryBean允许开发者定制Bean的创建过程,这在创建复杂对象时非常有用。例如,你可能需要从某个外部系统加载配置信息,然后根据这些信息实例化Bean。这种灵活性使得FactoryBean能够处理各种复杂的创建逻辑。

2‌、延迟初始化‌:通过使用FactoryBean,可以控制Bean的初始化时机,延迟到真正需要时再进行实例化,从而提高系统性能。 ‌

3、创建代理对象‌:FactoryBean常用于创建AOP(面向切面编程)代理对象,特别是在使用Spring AOP时。这允许在Bean实例化的过程中动态生成代理对象,实现横切关注点的注入,如安全、事务管理等。 ‌

4、封装复杂配置‌:如果一个Bean的配置非常复杂,可以将这些配置逻辑封装到FactoryBean中,从而简化Spring配置文件或注解配置。这有助于减少配置的复杂性,提高系统的可维护性。

5‌、单例模式实现‌:FactoryBean可以控制Bean实例的创建和管理,确保每次获取的都是同一个实例,从而实现单例模式。

6‌、实现一些初始化操作‌:在Bean实例化的过程中,FactoryBean可以进行一些初始化操作,如资源加载、参数配置等。 

接下来再聊聊FactoryBean在开源框架中的使用,FactoryBean在Dubbo,Mybatis,Feign中都有使用到。

例如dubbo中的ReferenceBean实现了FactoryBean,ReferenceBean是处理dubbo注解的时候会将@DubboReference注解处理为ReferenceBean,getObject方法就是对@DubboReference修饰的变量做一个动态代理,当真正使用到这个变量调用远程服务的时候,获取到代理对象进行远程调用

还有mabatis中的MapperFactoryBean也应用了FactoryBean的特性,通过利用Spring的扫描后,会把mybatis中的mapper接口接口扫描出来并且得到对应的BeanDefinition,接下来把扫描得到的BeanDefinition进行修改,把BeanClass修改为MapperFactoryBean; 扫描完成后,Spring就会基于BeanDefinition去创建Bean了,相当于每个Mapper对应一个 FactoryBean, 在MapperFactoryBean中的getObject方法中,调用了getSqlSession()去得到一个sqlSession 对象,然后根据对应的Mapper接口生成一个Mapper接口代理对象,这个代理对象就成为 Spring容器中的Bean。

还有springcloud中的feign也使用了FactoryBean的特性,@FeignClient修饰的接口被spring扫描成beanDefinition之后,将beanDefinition的beanClass对象修改为了FeignClientFactoryBean,最终使用的时候getObject方法返回的是代理对象进行调用。

经过FactoryBean在以上三个框架中的使用,发现FactoryBean在框架中的经常使用就是生成复杂的代理对象。以上就是FactoryBean实例化流程与使用场景的所有内容


http://www.kler.cn/news/361927.html

相关文章:

  • 【银河麒麟高级服务器操作系统-实例】集群存储文件系统异常,本地复现+详细分析+解决建议
  • Jupyter Notebook汉化(中文版)
  • 超简洁的B端系统,还是看国外的设计.
  • 自由学习记录(13)
  • 【C++】使用vscode进行 C/C++ 开发,内含c_cpp_properties.json、launch.json 和 tasks.json解释
  • vscode 预览markdown 文件
  • 【uniapp】使用Promise封装request
  • 大厂面试真题-了解云原生吗,简单说一下docker和k8s
  • electron-vite_10electron-updater软件更新
  • 【C语言】原码 反码 补码
  • 【知识科普】websocket深入了解
  • 糖果——差分约束 + 正环判定及其优化(手搓栈 + 标记法)
  • 搜维尔科技:Varjo XR-4 模拟驾驶
  • LeetCode 1750.删除字符串两端相同字符后的最短长度
  • Lattice_FPGA使用Synplify Pro进行综合
  • flv格式如何转换mp4?将flv转换成MP4格式的9种转换方法
  • 如何将 Elasticsearch 与流行的 Ruby 工具结合使用
  • Linux下进行用户的切换与创建以及细微设置
  • SIMPLOT: Enhancing Chart Question Answering by Distilling Essentials
  • LeetCode两数相加
  • ECharts饼图-饼图标签对齐,附视频讲解与代码下载
  • 情怀程序员,没有套路的坐下和大家掏心窝聊聊今年的1024 | 程序员节
  • 通过DevTools逃离Chrome沙盒(CVE-2024-6778和CVE-2024-5836)
  • 删除本地文件不影响Github
  • Centos7 安装部署Zookeeper
  • AMR机器人助力废料管理,实现生产空间最大化利用