spring中的FactoryBean與ObjectFactory的區別

OkidoGreen發表於2020-10-07

一、介面定義 :

public interface FactoryBean<T> {
    //獲取物件的工廠方法
    @Nullable
    T getObject() throws Exception;
    //物件型別
    @Nullable
    Class<?> getObjectType();
    //是否是單例,這個屬性決定了spring是否基於快取來將它維護成一個單例物件。
    default boolean isSingleton() {
        return true;
    }
}
 
 
 
public interface ObjectFactory<T> {
    //獲取物件的工廠方法。
    T getObject() throws BeansException;
}

通過介面內容來看,兩者都是屬於工廠模式用來建立物件使用的。
而區別在於
FactoryBean在BeanFacotry的實現中有著特殊的處理,如果一個物件實現了FactoryBean 那麼通過它get出來的物件實際是
factoryBean.getObject() 得到的物件,如果想得到FactoryBean必須通過在 '&' + beanName 的方式獲取

而ObjectFactory則只是一個普通的物件工廠介面。
在檢視AbstractBeanFacotry的doGetBean(..) 部分的原始碼時,可以看到spring對ObjectFactory的應用之一就是,將建立物件
的步驟封裝到ObjectFactory中 交給自定義的Scope來選擇是否需要建立物件來靈活的實現scope。


通過這方面簡單的對比可以得到:

    FactoryBean的著重於自定義建立物件過程,由BeanFactory通過FactoryBean來獲取目標物件,而如果是isSingleton返回true的
    話spring會利用單例快取來快取通過FactoryBean建立的物件。

    而ObjectFactory就是一個普通的工廠物件介面,對於spring在doGetBean處的使用時,在於建立物件的過程由框架通過ObjectFactory定義,而
    建立的時機交給擴充介面Scope,除此之外ObjectFactory就是一個普通的介面。
    此外在將給依賴注入列表註冊一個ObjectFactory型別的物件,在注入過程中會呼叫objectFactory.getObject()來建立目標物件注入進去。
    (如beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());)

    簡單來說就是通過FactoryBean你可以控制物件如何建立,而ObjectFactory藉助Scope介面自定義scope你可以控制物件的建立時機。


三、例子:

car.java

 
public class Car {
    private int maxSpeed;
    private String brand;
    private double price;
 
    public int getMaxSpeed() {
        return maxSpeed;
    }
 
    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
 
    public String getBrand() {
        return brand;
    }
 
    public void setBrand(String brand) {
        this.brand = brand;
    }
 
    public double getPrice() {
        return price;
    }
 
    public void setPrice(double price) {
        this.price = price;
    }
 
    @Override
    public String toString() {
        return "Car{" +
                "maxSpeed=" + maxSpeed +
                ", brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}
CarFactoryBean.java
public class CarFactoryBean implements FactoryBean<Car> {
 
    @Override
    public Car getObject() throws Exception {
        Car car = new Car();
        car.setMaxSpeed(260);
        car.setBrand("寶馬");
        car.setPrice(500000);
        return car;
    }
 
    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }
 
    @Override
    public boolean isSingleton() {
        return true;
    }
 
 
}
  1.  spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="carFactoryBean" class="hong.factoryBean.CarFactoryBean" >
 
    </bean>
</beans>

 

Test.java

public class Test {
 
    public static void main(String args[]) {
        Resource resource = new ClassPathResource("hong/factoryBean/spring-config.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
 
        System.out.println(beanFactory.getBean("carFactoryBean").toString());
        System.out.println(beanFactory.getBean("&carFactoryBean").toString());
 
    }
 
 
}

相關文章