FactoryBean源码解析

得意时要看淡,失意时要看开。不论得意失意,切莫大意;不论成功失败,切莫止步。志得意满时,需要的是淡然,给自己留一条退路;失意落魄时,需要的是泰然,给自己觅一条出路FactoryBean源码解析,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、简介

FactoryBean 是 Spring 框架中的一个接口,用来创建特定类型的 Bean 对象。实现FactoryBean 接口就可以自定义 Bean 对象的创建过程。FactoryBean 本身也是 Bean,会在 Spring 中经历 Bean 的生命周期,而由 FactoryBean 创建的 Bean 不经历 Bean 的生命周期。

二、FactoryBean 接口的方法

FactoryBean 内部包含了一下三个方法:

  • getObject()FactoryBean 最重要的方法,用于返回被管理的Bean对象的实例。
  • getObjectType():返回的 Bean 对象的类型。
  • isSingleton():用于指示返回的 Bean 对象是否为单例。

三、FactoryBean 与 BeanFactory 的区别

有的人分不清 FactoryBeanBeanFactory ,其实只要是粗略看过 Spring 源码的人,都会知道,BeanFactory 是 Spring 容器的顶层接口,这个接口定义了 Spring 容器最基本的功能,如从容器中获取 Bean,判断 Bean 是不是单例等,归根结底它是一个工厂,或者是一个容器,用来创建和管理 Bean 的,而 FactoryBean 是一种特殊的 Bean,注意它是个 Bean,只不过它让我们可以自定义创建 Bean 的过程。

四、源码解析

首先我们先找到 Spring 启动时,初始化 Bean 的核心方法,位于 AbstractApplicationContextrefresh 方法里的 finishBeanFactoryInitialization(beanFactory),在这个方法里,找到最后一行最核心的方法 beanFactory.preInstantiateSingletons() ,在这个方法里,找到下面这段代码。

image-20230719152725153

这段代码是从 Spring 容器里获取所有的非抽象的单例的非懒加载的 Bean,然后判断是不是 FactoryBean,如果不是,就直接调用 getBean 方法完成初始化,如果是,就判断是不是需要紧急初始化。

这里需要注意,FactoryBean 也是做为一个 Bean 放在 Spring 容器里的,从容器里获取这个 FactoryBean 实例,需要在名称前加上 & 符号,如果不加的话,获取的是 FactoryBean 创建出来的 Bean 实例,所以这里通过 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 这样获取,这个 FACTORY_BEAN_PREFIX 就是 & 符号。

另外这里出现了 SmartFactoryBean 这个接口,这个接口是 FactoryBean 的子接口,其内部通过 isEagerInit 方法来控制是否紧急初始化,所以这里代码的意思就是,如果是 SmartFactoryBean 类型的 FactoryBean 并且 isEagerInit 是 true 的,才会立即调用 getBean 方法完成初始化。

我们继续跟着 getBean 方法往里看

image-20230719155738013

继续跟进 doGetBean,找到创建 Bean 实例的核心代码

image-20230719160208193

在调用完 getSingleton 方法后,会将 FactoryBean 实例放到 Spring 容器里,再调用 getObjectForBeanInstance 方法获取 Bean 实例,我们跟进去看看

image-20230719161353731

继续跟进

image-20230719161649962

第一个if判断,用处是防止那种不是 FactoryBean,但是前面带了 & 符号进来的。

第二个if判断,就是如果是普通的 bean 或者是 FactoryBean,就返回其实例本身,这就是我们上面说的,如果 FactoryBeanbeanName 前面带了 & 符号,就返回 FactoryBean 本身。

能继续往下走,就说明一定是 FactoryBean 了,所以类型强转后,调用 getObjectFromFactoryBean 方法,我们继续跟进

image-20230719162451554

这里用了一些缓存的机制,我们不用管,继续跟进 doGetObjectFromFactoryBean 方法

image-20230719162647762

我们可以看到,最终调用了 FactoryBeangetObject 方法

五、实际应用

FactoryBean 的实际应用场景有很多,例如 SpringAop 的 ProxyFactoryBean 用来创建 AOP 代理,Mybatis 的 MapperFactoryBean 用来创建 Mapper 的代理对象,Fegin 的 FeignClientFactoryBean 用来创建远程服务代理。

有兴趣的小伙伴,可以在任意一个 FactoryBeangetObject() 方法上打上断点,启动服务,看看具体的方法调用栈,可以更好的帮助学习源码。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/154469.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!