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ū)別

