-
Spring 为什么会有 FactoryBean?
作者:叁滴水
博客:https://blog.csdn.net/qq_30285985/
前言
常说 spring 的核心是 ioc,ioc 的核心是 BeanFactory。然而在 spring 中还有一个很容易让人混淆的词FactoryBean。
本文通过一些 mybatis 源码来讲述其区别,请大家参考。另外,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 Java、Spring 系列面试题和答案,非常齐全。
一、为什么会有FactoryBean?
BeanFactory
是在学习 IOC 第一课的时候就遇到的,它是生产 bean 的工厂,在此工厂中,我们可以生产出我们想要的 bean,并且通过getBean
接口进行获取。
但是在通过getBean
获取 bean 之前,我们需要事先定义这个 bean 长什么样子,或者说它由哪些组件组成。
定义的方式有很多,可以通过xml进行定义,或者在代码中通过注解(@Bean、@Service)进行定义。
就好比一个 Controller,在最原始的 xml 配置 bean 的时候,我们需要定义它是由哪些service组成,然后一点点的配置好,xml要与 Controller 的service一一对应起来。
这种方式的弊端是所有的bean
都需要事先定义好,但是有时候,有的一些bean
,我们只知道它大概的样子,但是无法事先定义出其具体的功能。就好比,我们知道它是一只鸟,但是不知道是什么种类的鸟,只有在代码执行的时候,我才知道是什么种类的鸟。
如此表达可能不太直观,这里可以直接联想出mybatis
中的mapper
,例如UserMapper
。
在定义UserMapper
的时候,我们知道其最后执行的xml的sql语句。而且这样的mapper
又很多,可能还会有更多的OrderMapper、GoodsMapper
等等。 如果每一个都一一定义的话,会非常的麻烦。
但是,我们发现mapper
中的功能都是与数据库交互的代码。因此规范其写法,通过定义一些标准的写法,就可以简化其定义过程。这样便出现了@Select
注解和@Update
注解(还有xml的标签),这样我们只需要在注解中写入对应的sql,在代码执行时候,执行对应的sql。
这样一想可以认为是所有的mapper就是鸟,但是不知道它是什么鸟,或者这个鸟是做什么的(不知道每个mapper
的功能),在真正创建它的时候,才去关注它具体的内容。
这样FactoryBean
的就有了其意义,它可以定义出一种类型的Bean,并且在创建的时候再去实现其具体的功能。
里面有三个方法:
-
getObject 获取
bean
方法,在此方法中,我们可以自己定义一个对象,然后自行修改其创建过程。通过这个方法,我们可以在mapper
创建的时候再实现其具体的功能。 - getObjectType 获取这类的类型。
- isSingleton 是否单例。
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
二、通过源码深入学习FactoryBean
如果还没有理解FactoryBean
,我们可以通过学习mybatis
源码,来更加深入的了解FactoryBean。
这里带领大家了解下Mybatis
的MapperFactoryBean
,这个是生成Mapper
的FactoryBean
。
大家可以自行打开源码查看,通过上图的流程即可发现,每一个mapper
是通过MapperFactoryBean
的getObject
方法进行创建,最后生成一个代理类。
相信跟一下mybatis
的源码之后,对FactoryBean
会有更加深入的理解。
虽然在开发时用FactoryBean
的机会并不多,但是源码中会经常遇到,例如spring cloud
的feign
组件,里面肯定也会看到FactoryBean
的身影。
对于 mybatis 和 feign,可以很轻松的发现其共同点:
-
存在一种类型的bean。
mybatis
是Mapper
,feign
是FeignClient
。 -
这种
bean
功能单一。mapper
只跟数据库做交互。FeignClient
只是接口调用。
还有我们常用的定时器框架 quartz 框架,里面也有 JobDetailFactoryBean,Redis 中有 RedisClientFactoryBean,security 框架的 UserDetailsManagerResourceFactoryBean。
其实他们都是有一个共同的特点,就是生产的 bean 是一种类型,在创建的过程中在实现其功能。
到这是不是已经理解了FactoryBean呢?
本文来自作者「叁滴水」投稿,谢谢分享
原文:https://www.cnblogs.com/javastack/p/14808636.html