工廠方法在Spring源碼中的運用

我們都知道Spring中IOC是使用的工廠模式,但是對于實現細節就一知半解了,今天這篇文章就帶大家解讀Spring中是如何使用工廠模式的 。
在上篇文章中我們懂了什么是工廠模式 , 這篇文章就帶著學過的概念深入到Spring的內部看看究竟是怎么使用該模式的 。
在Spring中使用工廠方法的是BeanFactory和FactoryBean<>接口 。
一、BeanFactory使用工廠方法使用了Spring框架,我們就很少自己進行對象的創建了,而我們使用到的對象當然就是交給Spring的工廠模式來創建的了 。
其中BeanFactory是Spring容器的頂層接口,也是Bean工廠最上層的接口,其會有很多工廠實現例如ClassPathXmlApplicationContext、XmlWebApplicationContext其中最常見的就是DefaultListableBeanFactory,我們可以把BeanFactory看成是一種工廠方法模式 。

工廠方法在Spring源碼中的運用

文章插圖
在工廠方法模式中有四個角色:
1、抽象工廠(Abstract Factory):提供了創建產品的接口,調用者通過它訪問具體工廠的工廠方法 createProduct() 來創建產品 。
2、具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法 , 完成具體產品的創建 。
3、抽象產品(Product):定義了產品的規范 , 描述了產品的主要特性和功能 。
4、具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來創建,它同具體工廠之間一一對應 。
BeanFactory是角色中的抽象工廠,而getBean就相當于我們實例中的createProduct()方法,用于創建對象 。
DefaultListableBeanFactory等實現的工廠類就是角色中的具體工廠 。
產品就是在我們開發中加上注解的@Controller@Service@compent@Configuration的類,Spring會將他們當成產品使用工廠模式生成對象 。
在我們createProduct方法中是直接創建的對象 , Spring肯定不會這么的笨,我們接著看getBean方法的實現方法 。
getBean方法中一系列鏈路最終調用到doGetBean方法用于創建對象,在doGetBean中創建對象使用的是設計模式中的代理模式 。
二、FactoryBean<>使用工廠方法講完BeanFactory,再介紹另外一個工廠模式的應用FactoryBean<> , 想必大家也經常會比較這倆 。
實際上,這兩個接口都是用于創建對象,都可以看做是工廠方法模式的實現 。
FactoryBean<>工廠通過getObject()方法來創建并返回對象,我們可以通過實現FactoryBean<>來定制化自己需要的Bean對象 。
工廠方法在Spring源碼中的運用

文章插圖
既然FactoryBean<>是留個開發者實現的,我們就手動實現一個FactoryBean<> 。
@Componentpublic class MyFactoryBean<> implements FactoryBean<><Product>, BeanNameAware {private String name;@Overridepublic Product getObject() throws Exception {return new Product();}@Overridepublic Class<?> getObjectType() {return Product.class;}@Overridepublic boolean isSingleton() {return false;}@Overridepublic void setBeanName(String s) {this.name = name;}}接著我們分別使用兩種方式getBean 。
public static void main(String[] args) {//測試FactoryBean<>ApplicationContext ac =new AnnotationConfigApplicationContext(MyFactoryBean<>.class);System.out.println(ac.getBean("myFactoryBean<>"));System.out.println(ac.getBean("&myFactoryBean<>"));}只是在獲取Bean時加了一個&會出現兩種情況 。
【工廠方法在Spring源碼中的運用】cn.sky1998.create.methodFactory.Product@52a86356cn.sky1998.create.methodFactory.MyFactoryBean<>@5ce81285doGetBean里面進行了判斷是否是FactoryBean<>的實現類 。
Spring對FactoryBean<>的實現機制是當你獲取一個Bean時,如果獲取的Bean的類型是FactoryBean<> , 并且其name中并沒有&則調用bean的getObject方法獲取FactoryBean<>實現類中提供bean,否則就是直接返回普通的bean類型 。
當我們在引入其他框架整合Spring時 , 便會有很多橋接整合包,例如mybatis-spring等,其中就會有FactoryBean<>的實現,例如SqlSessionFactoryBean<>、MapperFactoryBean<>等,將需要整合的定制化Bean通過工廠方法的模式 , 加入進Spring容器中 。
當我們整合Mybatis時無論是多么的Bean都能很好的處理,mybatis-spring中的FactoryBean<>正是將Mybatis的核心啟動類給調用出來 。
三、BeanFactory和FactoryBean<>的異同BeanFactory是Spring的一個大工廠,創建著Spring框架運行過程中所需要的Bean;

推薦閱讀