Spring中的FactoryBean實現原理詳解
1、概述
spring中有兩種類型的Bean:
- 一種是普通的JavaBean;
- 另一種就是工廠Bean(FactoryBean)
這兩種Bean都受Spring的IoC容器管理,但它們之間卻有一些區(qū)別。
2、詳述
普通的JavaBean不再多說,我們將其定義好,然后在配置文件中定義并配置其依賴關系,就可以通過IoC容器的getBean獲取到。
那么FactoryBean呢?
FactoryBean跟普通Bean不同,它是實現了FactoryBean<T>接口的Bean,通過BeanFactory類的getBean方法直接獲取到的并不是該FactoryBean的實例,而是該FactoryBean中方法getObject返回的對象。但我們可以通過其它途徑獲取到該FactoryBean的實例,方法就是在通過getBean方法獲取實例時在參數name前面加上“&”符號即可。
FactoryBean接口提供的方法如下:
public interface FactoryBean<T> { //獲取FactoryBean初始化的Bean實例 T getObject() throws Exception; //獲取Bean實例的類型 Class<?> getObjectType(); //判斷是否是單例模式 boolean isSingleton(); }
3、示例
創(chuàng)建MyFactoryBean
public class MyFactoryBean implements FactoryBean<Date>,BeanNameAware { private String name; @Override public Date getObject() throws Exception { return new Date(); } @Override public Class<?> getObjectType() { return Date.class; } @Override public boolean isSingleton() { return false; } public void sayName() { System.out.println("My name is " + this.name); } @Override public void setBeanName(String name) { this.name = name; } }
在Spring的配置文件ApplicationContext.xml中注入MyFactoryBean
<bean id ="myFactoryBean" class="com.xxxx.MyFactoryBean"></bean>
測試代碼
public class MainFactoryBean { @SuppressWarnings("resource") public static void main(String [] args){ ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml"); Date now = (Date) appCtx.getBean("myFactoryBean"); System.out.println(now); MyFactoryBean factoryBean = (MyFactoryBean) appCtx.getBean("&myFactoryBean"); factoryBean.sayName(); } }
運行結果
通過myFactoryBean名稱獲取到的Bean是Date對象實例,通過&myFactoryBean獲取到的是MyFactoryBean對象實例。
4、實現原理
我們來看一下執(zhí)行Date now = (Date) appCtx.getBean("myFactoryBean"); 時會做的處理操作。 AbstractBeanFactory中會進行一系列的操作。
getBean獲取bean
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
doGetBean中獲取bean實例
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { .........//省略部分代碼 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); .........//省略部分代碼 return (T) bean; }
getObjectForBeanInstance中會選擇bean實例是普通的Bean還是FactoryBean,同時通過判斷name中是否有&來選擇判斷是或者FactoryBean還是其getObject方法中獲取的bean
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { .........//省略部分代碼 //判斷bean類型是否是FactoryBean,或者name是否是以&開頭,如果是則直接返回 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } //如果是則從getObjectFromFactoryBean中獲取 if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
getObjectFromFactoryBean接下來會執(zhí)行FactoryBean的getObject方法獲取bean了。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { .........//省略部分代碼 Object object = doGetObjectFromFactoryBean(factory, beanName); .........//省略部分代碼 return object; } private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object; .........//省略部分代碼 //調用Factory的getObject方法 object = factory.getObject(); .........//省略部分代碼 return object; }
總結
Spring對FactoryBean的實現機制是當你獲取一個Bean時,如果獲取的Bean的類型是FactoryBean,并且其name中并沒有&則調用bean的getObject方法獲取FactoryBean實現類中提供bean,否則就是直接返回普通的bean類型。
到此這篇關于Spring中的FactoryBean實現原理詳解的文章就介紹到這了,更多相關FactoryBean實現原理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Spring中的BeanFactory與FactoryBean區(qū)別詳解
- SpringBoot升級3.2報錯Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String的解決方案
- Spring中的FactoryBean與ObjectFactory詳解
- Spring中BeanFactory與FactoryBean的區(qū)別解讀
- Spring中的FactoryBean與BeanFactory詳細解析
- Spring的FactoryBean<Object>接口示例代碼
- 簡單了解Spring中BeanFactory與FactoryBean的區(qū)別