Spring中的FactoryBean與ObjectFactory詳解
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?Boot自動配置的原理及@Conditional條件注解
這篇文章主要介紹了Spring?Boot自動配置的原理及@Conditional條件注解,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的朋友可以參考一下2022-07-07Mybatis-plus自動填充不生效或自動填充數(shù)據(jù)為null原因及解決方案
本文主要介紹了Mybatis-plus自動填充不生效或自動填充數(shù)據(jù)為null原因及解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-05-05SSM+微信小程序?qū)崿F(xiàn)物業(yè)管理系統(tǒng)及實例代碼
這篇文章主要介紹了SSM+微信小程序?qū)崿F(xiàn)物業(yè)管理系統(tǒng),ssm微信小程序物業(yè)管理系統(tǒng),有網(wǎng)站后臺管理系統(tǒng),本文通過實例代碼給大家展示系統(tǒng)的功能,需要的朋友可以參考下2022-02-02java設(shè)計模式原型模式與享元模式調(diào)優(yōu)系統(tǒng)性能詳解
這篇文章主要為大家介紹了java設(shè)計模式原型模式與享元模式調(diào)優(yōu)系統(tǒng)性能方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05如何使用RequestHeaders添加自定義參數(shù)
這篇文章主要介紹了使用RequestHeaders添加自定義參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。2022-02-02spring mail借助qq郵箱服務(wù)器發(fā)送郵件
這篇文章主要介紹了spring mail借助qq郵箱服務(wù)器發(fā)送郵件的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12