BeanFactory 是字面意思是“Bean 工廠”,那麼顧名思義“Bean 工廠”就是用來生產 Bean 或者是用來存放 Bean 的嗎?
實際上 BeanFactory
是一個 Spring IoC 容器
。
那這個“Bean 工廠”是如何實現的呢?
BeanFactory 接口
這是一個最簡單的容器,它主要的功能是爲依賴注入 (DI) 提供支持,這個容器接口在 org.springframework.beans.factory.BeanFactor 中被定義。
我們實際使用的 “Bean 工廠” 都是 BeanFactory 接口的實現類,例如:
- XmlBeanFactory(用來讀取配置文件)
- StaticListableBeanFactory
- DefaultListableBeanFactory
//利用 ClassPathResource() 去加載在路徑 CLASSPATH 下可用的 bean 配置文件
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring.xml"));
BeanFactory 代碼實現
看完概念可能還是有點懵,不要着急再往下看看。
Animal.java(接口)
public interface Animal {
void eat();
}
Cat.java(實現Animal接口)
public class Cat implements Animal {
public void eat() {
System.out.println("貓喫魚");
}
}
BeanFactory.java(“Bean 工廠”)
import java.util.HashMap;
import java.util.Map;
public class BeanFactory {
private Map<String, Object> beans = new HashMap<>();
public void addBeans(String id, Object bean) {
beans.put(id, bean);
}
public Object getBeans(String id) {
return beans.get(id);
}
}
BeanUtils.java(工具類封裝 BeanFactory )
public class BeanUtils {
//靜態變量
private static BeanFactory beanFactory =new BeanFactory();
//靜態塊 只執行一次
//使用靜態塊實現了 BeanFactory(Spring IoC 容器)在創建的時候就實例化了Bean,而不是在 getBean 時才實例化Bean
static {
beanFactory.addBeans("Animal",new Cat());
}
//靜態方法(類調用)
public static Object getBean(String id) {
return beanFactory.getBeans(id);
}
}
Tips:這裏爲什麼要創建BeanUtils
來封裝BeanFactory
呢?因爲BeanFactory
是一個 Spring IoC 容器
,在 Spring
中容器將創建對象並進行配置管理,而不是我們主動的去 new
一個對象,也是爲依賴注入 (DI)
提供支持。
MainTest.java(測試)
public class MainTest {
public static void main(String[] args) {
//使用BeanUtils直接調用靜態方法getBean就獲取了Bean
Animal animal = (Animal) BeanUtils.getBean("Animal");
animal.eat();
}
}
以上就是對 BeanFactory ( Spring IoC 容器)的簡單實現,可以將BeanFactory 理解爲一個存放和管理 Bean 的集合(至於 Spring 底層源碼使用的是什麼集合我不確定,但是肯定比這個簡單實現要複雜很多)。
FactoryBean 接口
說完了 BeanFactory,那麼疑問又來啦,FactoryBean 又是什麼呢?
簡單的說,BeanFactory 是 Factory 結尾是工廠;FactoryBean 是Bean 結尾是 Bean實例,但是這個Bean 實現了 FactoryBean
接口。
Bean 分類
Spring 中 Bean分爲兩種,具體如下:
1. 普通的Bean: < bean id="xxx" class="xxx">
,Spring 直接創建 Bean 實例
2. FactoryBean: FactoryBean 是接口,爲IOC容器中Bean的實現提供了更加靈活的方式;是一個特殊的bean,具有工廠生成對象的能力,只能生成特定的對象。Bean必須實現 FactoryBean接口,此接口提供方法 getObject() 用於獲得特定bean。
FactoryBean(源碼)
public interface FactoryBean<T> {
// 屬性名
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
// 獲取bean實例,實例化bean 的邏輯就在這裏實現
@Nullable
T getObject() throws Exception;
// 獲取bean類型
@Nullable
Class<?> getObjectType();
// 是否是單例
default boolean isSingleton() {
return true;
}
}
getObject()
返回 FactoryBean 管理的Bean 實例,並不是FactoryBean 本身的實例。- FactoryBean 管理的對象可以是 singleton (單例)也可以是prototype (非單例),所以此接口有了方法
isSingleton()
返回由FactoryBean 創建的Bean 實例的作用域是singleton還是prototype。 getObjectType()
最主要的目的就是在不創建實例的情況下就能知道想要創建的Bean 實例的類型。
Tips:從Spring3.0開始,FactoryBean開始支持泛型,即接口聲明改爲FactoryBean<T>
的形式。
FactoryBean 與普通的 Bean 區別
FactoryBean不同於普通Bean的是:它是實現了FactoryBean<T>接口
的Bean
,根據該Bean的ID
從BeanFactory
中獲取的實際上是 FactoryBean的getObject()返回的特定 Bean 實例
,而不是FactoryBean 本身
,如果要獲取FactoryBean對象,需要在Bean id 前加一個 & 符號來獲取。