最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中的FactoryBean與ObjectFactory詳解

 更新時間:2023年12月20日 09:16:29   作者:Brain_L  
這篇文章主要介紹了Spring中的FactoryBean與ObjectFactory詳解,FactoryBean是一種特殊的bean,本身又是個工廠,實現(xiàn)了FactoryBean的bean會被注冊到容器中,需要的朋友可以參考下

FactoryBean

public interface FactoryBean<T> {
    //獲取對象
    T getObject() throws Exception;
    //獲取對象類型
    Class<?> getObjectType();
    //是否單例,默認true
    default boolean isSingleton() {
		return true;
	}
}

FactoryBean是一種特殊的bean,本身又是個工廠,實現(xiàn)了FactoryBean的bean會被注冊到容器中。

ObjectFactory

public interface ObjectFactory<T> {
   //獲取對象
   T getObject() throws BeansException;
}

ObjectFactory就是個對象工廠。

示例對比

public class Cat {
    public Cat() {
        System.out.println("調(diào)用了Cat構(gòu)造器");
    }
}
@Component
public class MyFactoryBean implements FactoryBean<Dog> {
    @Override
    public Dog getObject() throws Exception {
        return new Dog();
    }
    @Override
    public Class<?> getObjectType() {
        return Dog.class;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
}

MyFactoryBean用來生成Dog對象。

public class Cat {
    public Cat() {
        System.out.println("調(diào)用了Cat構(gòu)造器");
    }
}
@Component
public class MyObjectFactory implements ObjectFactory<Cat> {
    @Override
    public Cat getObject() throws BeansException {
        return new Cat();
    }
}

MyObjectFactory用來生成Cat對象。

System.out.println(ctx.getBean("myFactoryBean"));
System.out.println(ctx.getBean("myFactoryBean"));
System.out.println(ctx.getBean("&myFactoryBean"));
System.out.println(((MyObjectFactory)ctx.getBean("myObjectFactory")).getObject());
//輸出:
調(diào)用了Dog構(gòu)造器
com.brain.demo.factory.Dog@58c1da09
com.brain.demo.factory.Dog@58c1da09
com.brain.demo.factory.MyFactoryBean@2b2954e1
調(diào)用了Cat構(gòu)造器
com.brain.demo.factory.Cat@58d6e55a

ObjectFactory沒啥說的,就是對象工廠,通過getObject獲取對象。

重點看下FactoryBean。MyFactoryBean本身作為bean(“myFactoryBean”)被掃描進容器中,即singletonObjects。當通過getBean或者@Autowired等方式需要獲得bean時,調(diào)用getObject或者從緩存中獲取所需的對象。

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   //名稱轉(zhuǎn)換
   final String beanName = transformedBeanName(name);
   Object bean;
   // Eagerly check singleton cache for manually registered singletons.
   Object sharedInstance = getSingleton(beanName);
   //這個地方獲得到bean("myFactoryBean")
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      //這里進行了轉(zhuǎn)換
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
}
protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
   // Don't let calling code try to dereference the factory if the bean isn't a factory.
   //判斷name是否是&開頭的,代表是FactoryBean
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      if (beanInstance instanceof NullBean) {
         return beanInstance;
      }
      if (!(beanInstance instanceof FactoryBean)) {
         throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
      }
      if (mbd != null) {
         mbd.isFactoryBean = true;
      }
      return beanInstance;
   }
   // Now we have the bean instance, which may be a normal bean or a FactoryBean.
   // If it's a FactoryBean, we use it to create a bean instance, unless the
   // caller actually wants a reference to the factory.
   //不是FactoryBean,就是普通的bean,返回
   if (!(beanInstance instanceof FactoryBean)) {
      return beanInstance;
   }
   Object object = null;
   if (mbd != null) {
      mbd.isFactoryBean = true;
   }
   else {
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {
      // Return bean instance from factory.
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      // Caches object obtained from FactoryBean if it is a singleton.
      if (mbd == null && containsBeanDefinition(beanName)) {
         mbd = getMergedLocalBeanDefinition(beanName);
      }
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      //調(diào)用FactoryBean的getObject方法獲取bean
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}
protected Object getCachedObjectForFactoryBean(String beanName) {
        //factoryBeanObjectCache就是用來存放FactoryBean getObject生成的對象,此時還不包含我們需要的bean
		return this.factoryBeanObjectCache.get(beanName);
}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   //單例且singletonObjects中已經(jīng)加載了FactoryBean
   if (factory.isSingleton() && containsSingleton(beanName)) {
      synchronized (getSingletonMutex()) {
         //第一次進來是獲取不到的
         Object object = this.factoryBeanObjectCache.get(beanName);
         if (object == null) {
            //調(diào)用getObject,此時生成了Dog實例,打印“調(diào)用了Dog構(gòu)造器”
            object = doGetObjectFromFactoryBean(factory, beanName);
            // Only post-process and store if not put there already during getObject() call above
            // (e.g. because of circular reference processing triggered by custom getBean calls)
            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
            if (alreadyThere != null) {
               object = alreadyThere;
            }
            else {
               if (shouldPostProcess) {
                  if (isSingletonCurrentlyInCreation(beanName)) {
                     // Temporarily return non-post-processed object, not storing it yet..
                     return object;
                  }
                  beforeSingletonCreation(beanName);
                  try {
                     //調(diào)用postProcessAfterInitialization,如果有AOP,此時生成代理對象
                     object = postProcessObjectFromFactoryBean(object, beanName);
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
                  finally {
                     afterSingletonCreation(beanName);
                  }
               }
               if (containsSingleton(beanName)) {
                  //將Dog放到緩存中,下次就可以取到了
                  this.factoryBeanObjectCache.put(beanName, object);
               }
            }
         }
         return object;
      }
   }
   else {
      Object object = doGetObjectFromFactoryBean(factory, beanName);
      if (shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;
   }
}

而要獲取MyFactoryBean就要通過“&myFactoryBean”才能獲取,getObjectForBeanInstance時通過BeanFactoryUtils.isFactoryDereference判斷beanName是不是以&開頭的,如果是,并且是FactoryBean類型的,則直接返回。

總結(jié)

FactoryBean本身作為bean保存在singletonObjects,beanName和普通bean一樣,首字母小寫(如果你沒指定的話)。

如果直接通過beanName獲取到的是FactoryBean通過getObject生成的對象,生成的對象保存在factoryBeanObjectCache中,便于下次獲取時不用再調(diào)用getObject。

如果想獲取FactoryBean本身,需要通過&beanName來獲取,容器根據(jù)前綴&和是否是FactoryBean,來從singletonObjects中獲取bean。

ObjectFactory是一個普通工程,通過getObject生成對象,不會像上面進行緩存。

到此這篇關(guān)于Spring中的FactoryBean與ObjectFactory詳解的文章就介紹到這了,更多相關(guān)FactoryBean與ObjectFactory內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用Spring JPA中的@Version注解實現(xiàn)樂觀鎖

    利用Spring JPA中的@Version注解實現(xiàn)樂觀鎖

    樂觀鎖是數(shù)據(jù)庫和應(yīng)用程序中使用的一種并發(fā)控制策略,用于在多個事務(wù)嘗試更新單個記錄時確保數(shù)據(jù)完整性,Java Persistence API (JPA) 提供了一種借助@Version注解在 Java 應(yīng)用程序中實現(xiàn)樂觀鎖的機制,文中有詳細的代碼示例供大家參考,需要的朋友可以參考下
    2023-11-11
  • Java?Record的實現(xiàn)示例

    Java?Record的實現(xiàn)示例

    本文主要介紹了Java?Record的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • java簡單手寫版本實現(xiàn)時間輪算法

    java簡單手寫版本實現(xiàn)時間輪算法

    這篇文章主要為大家詳細介紹了java簡單手寫版本實現(xiàn)時間輪算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • IntelliJ IDEA JRebel 安裝使用圖文教程(熱部署插件)

    IntelliJ IDEA JRebel 安裝使用圖文教程(熱部署插件)

    IDEA 全稱 IntelliJ IDEA,是java語言開發(fā)的集成環(huán)境,IntelliJ在業(yè)界被公認為最好的java開發(fā)工具之一。這篇文章主要介紹了IntelliJ IDEA 熱部署插件JRebel 安裝使用圖文教程,需要的朋友可以參考下
    2018-03-03
  • SpringMVC中的攔截器與異常處理機制詳解

    SpringMVC中的攔截器與異常處理機制詳解

    這篇文章主要介紹了SpringMVC中的攔截器與異常處理機制詳解,SpringMVC的攔截器類似于Servlet開發(fā)中的過濾器Filter,用于對處理器進行預(yù)處理和后處理,需要的朋友可以參考下
    2024-01-01
  • SpringCloud全局過慮器GlobalFilter的用法小結(jié)

    SpringCloud全局過慮器GlobalFilter的用法小結(jié)

    這篇文章主要介紹了SpringCloud全局過慮器GlobalFilter的使用,全局過慮器使用非常廣泛,比如驗證是否登錄,全局性的處理,黑名單或白名單的校驗等,本文結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • Java實現(xiàn)短信驗證碼和國際短信群發(fā)功能的示例

    Java實現(xiàn)短信驗證碼和國際短信群發(fā)功能的示例

    本篇文章主要介紹了Java實現(xiàn)短信驗證碼和國際短信群發(fā)功能的示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • Spring Boot  Excel文件導(dǎo)出下載實現(xiàn)代碼

    Spring Boot Excel文件導(dǎo)出下載實現(xiàn)代碼

    這篇文章帶領(lǐng)我們直接實現(xiàn)Excel文件的直接導(dǎo)出下載,后續(xù)開發(fā)不需要開發(fā)很多代碼,直接繼承已經(jīng)寫好的代碼,增加一個Xml配置就可以直接導(dǎo)出。具體實現(xiàn)代碼大家跟隨小編一起通過本文學(xué)習(xí)吧
    2018-11-11
  • Java自定義數(shù)組列表的實現(xiàn)操作

    Java自定義數(shù)組列表的實現(xiàn)操作

    這篇文章主要介紹了Java自定義數(shù)組列表的實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • java迭代器基礎(chǔ)知識點總結(jié)

    java迭代器基礎(chǔ)知識點總結(jié)

    在本篇內(nèi)容里小編給大家整理了一篇關(guān)于java迭代器基礎(chǔ)知識點總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-01-01

最新評論

肇州县| 金沙县| 旺苍县| 南华县| 永吉县| 邓州市| 麦盖提县| 金川县| 浪卡子县| 屏南县| 通山县| 鄄城县| 富源县| 那曲县| 久治县| 富宁县| 绵竹市| 白玉县| 舞钢市| 和平区| 雷波县| 石狮市| 成安县| 泸水县| 怀集县| 青冈县| 改则县| 昆山市| 营山县| 微博| 东源县| 彩票| 保定市| 六枝特区| 嫩江县| 扶绥县| 大埔区| 宁远县| 明星| 沭阳县| 商城县|