1. 程式人生 > >(六)關於spring中的FactoryBean與ObjectFactory以及其區別

(六)關於spring中的FactoryBean與ObjectFactory以及其區別

1.檢視介面定義以及其區別

public interface FactoryBean<T> {
    //獲取物件的工廠方法
    @Nullable
    T getObject() throws Exception;
    //物件型別
    @Nullable
    Class<?> getObjectType();
    //是否是單例,這個屬性決定了spring是否基於快取來將它維護成一個單例物件。
    default boolean isSingleton() {
        return true;
    }
}
@FunctionalInterface
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你可以控制物件的建立時機。

2.demo

@Configuration
public class Application {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);
        ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        //註冊可被注入例項
beanFactory.registerResolvableDependency(Person.class, new StudentObjectFactory()); //新增BeanDefinition RootBeanDefinition objectXDef = new RootBeanDefinition(ObjectX.class); objectXDef.setScope(BeanDefinition.SCOPE_PROTOTYPE); applicationContext.registerBeanDefinition("objectX", objectXDef); //輸出[email protected] System.out.println(applicationContext.getBean("objectX", ObjectX.class).person); //輸出[email protected] System.out.println(applicationContext.getBean("myFactoryBean")); //true 多次獲取都是同一個物件 System.out.println(applicationContext.getBean("myFactoryBean") == applicationContext.getBean("myFactoryBean")); //獲取實際的工廠物件 //輸出[email protected]fad8c79 System.out.println(applicationContext.getBean("&myFactoryBean")); } @Bean public FactoryBean<Man> myFactoryBean(){ return new MyFactoryBean(); } public static class MyFactoryBean implements FactoryBean<Man>{ @Override public Man getObject() throws Exception { return new Man(); } @Override public Class<?> getObjectType() { return Man.class; } @Override public boolean isSingleton() { return true; } } public static class ObjectX { @Autowired Person person; } public static class Person { } public static class Man { } public static class StudentObjectFactory implements ObjectFactory<Person> { @Override public Person getObject() throws BeansException { return new Person(); } } }