spring中FactoryBean是什麼bean

北漂程式設計師發表於2021-07-01

前言

在spring中FactoryBean絕對是一種神奇的存在,和BeanFactory經常混淆,而且成為面試過程中經常被問到的問題,其實FactoryBean和BeanFactory很好理解,掌握一定的技巧即可。

初識

FactoryBean翻譯過來是工廠Bean,BeanFactory翻譯過來是Bean工廠,前者是bean工廠beanFactory中的一個bean,只不過這個bean和一般的bean不一樣,它有著自己的特殊之處,特殊在什麼地方那,在spring中提供了FactoryBean的介面,

package org.springframework.beans.factory;

import org.springframework.lang.Nullable;


public interface FactoryBean<T> {

    
    @Nullable
    T getObject() throws Exception;

    
    @Nullable
    Class<?> getObjectType();

    
    default boolean isSingleton() {
        return true;
    }

}

FactoryBean介面很簡單,就提供了三個方法getObject、getObjectType、isSingleton。就是這三個方法卻成為了spring中很多功能的基礎,搜尋整個spring的原始碼可以找到很多FactoryBean,除了spring自身提供的以外,在和一些框架進行整合的時候,同樣有FactoryBean的影子,比如和mybatis整合的時候的SqlSessionFactoryBean,

用法

這裡以springboot的環境為例演示下FactoryBean的用法,有需要原始碼的可關注公眾號【北漂程式設計師】私聊我。

自定義FactoryBean,僅在getObject方法內自己new了一個Student物件,且返回該物件;重寫了toString方法,為了測試用。

package com.example.myDemo.component;

import com.example.myDemo.po.Student;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

@Component
public class MyFactoryBean implements FactoryBean<Student> {

    @Override
    public Student getObject() throws Exception {

        Student student=new Student();
        return student;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public String toString() {
        return "MyFactoryBean{}";
    }
}

下面是Student類,很簡單就兩個屬性且重寫了toString方法,

package com.example.myDemo.po;

public class Student {
    private String name;
    private String code;

    public Student(String name, String code) {
        this.name = name;
        this.code = code;
    }

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{}";
    }
}

下面就是測試的方法了,

package com.example.myDemo;

import com.example.myDemo.component.MyFactoryBean;
import com.example.myDemo.po.Student;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.ApplicationContext;

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MyDemoApplication {

    public static void main(String[] args) {
        ApplicationContext ac=SpringApplication.run(MyDemoApplication.class, args);

        //獲得Student物件
        Student stu=(Student) ac.getBean("myFactoryBean");
        //獲得MyFactoryBean物件
        MyFactoryBean myFactoryBean=(MyFactoryBean) ac.getBean("&myFactoryBean");
        System.out.println("stu:"+stu);
        System.out.println("myFactoryBean:"+myFactoryBean);

    }

}

先看下列印結果,

列印結果很奇怪通過“myFactoryBean”獲得了Student物件,通過“&myFactoryBean”獲得了MyFactoryBean物件。為什麼會這樣

功能解釋

看了上面的輸出結果很多小夥伴都很詫異,沒錯這就是FactoryBean的神奇,通俗點講FactoryBean是一個工廠bean,它是一種可以生產bean的bean,通過其getObejct方法生產bean。當然不論是FactoryBean還是FactoryBean生產的bean都是受spring管理的這點是沒有問題的,不然通過getBean方法是拿不到的。

上面講了那麼多到底FactoryBean的用處是什麼,前面講到FactroyBean的作用是生產一個Bean,這裡有一個疑問spring就是用來生產bean和管理bean的,為什麼還要有FactoryBean,FactoryBean的真正目的是讓開發者自己去定義那些複雜的bean並交給spring管理,如果bean中要初始化很多變數,而且要進行許多操作,那麼使用spring的自動裝配是很難完成的,所以spring的開發者把這些工作交給了我們。一個比較常見的例子是,在mybatis和spring整合的時候便有這樣一個FactoryBean,名字叫SqlSessionFactoryBean,這個FactoryBean的目的就是返回一個spring管理的SqlSessionFactory,使用過mybatis的都知道要建立一個sqlSessionFactory需要配置很多屬性,所以便有了SqlSessionFactoryBean,下面看下SqlSessionFactoryBean,

看下sqlSessionFactoryBean的getObejct方法

public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
            this.afterPropertiesSet();
        }

        return this.sqlSessionFactory;
    }

getObejctType方法

public Class<? extends SqlSessionFactory> getObjectType() {
        return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
    }

isSingleton方法

public boolean isSingleton() {
        return true;
    }

總結

本篇文章主要帶小夥伴瞭解了FactoryBean這種特殊的Bean,它的作用就是生產Bean。這裡有個疑問在使用getBean方法的時候,為什麼傳入“myFactoryBean”和“&MyFactoryBean”兩個值返回值一個是FactoryBean生產的bean,一個是FactorBean那,下篇通過原始碼來揭祕,揭祕getObjectForBeanInstance方法的那些事,歡迎關注。

相關文章