從一個示例開始,先自定義一個類:java
package top.callback.demo.bean;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.ApplicationContext;
public class User {
private BeanFactory beanFactory;
private ObjectFactory<ApplicationContext> objectFactory;
// getter & setter
}
複製代碼
配置文件:spring
<bean id="user" class="top.callback.demo.bean.User" autowire="byType" />
複製代碼
測試程序:markdown
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/application-context.xml");
User user = beanFactory.getBean(User.class);
BeanFactory innerBeanFactory = user.getBeanFactory();
ObjectFactory<ApplicationContext> applicationContext = user.getObjectFactory().getObject();
System.out.println(beanFactory == innerBeanFactory); // false
System.out.println(beanFactory == applicationContext); // true
}
複製代碼
爲何 beanFactory
不等於 innerBeanFactory
,而等於 applicationContext
?app
按理說,User 對象是從 beanFactory 獲取的,那麼 user#beanFactory
和 beanFactory 應該是一個東西,但實際上倒是爹生了娃,但親子鑑定說娃不是親生的。這時候就要從 ClassPathXmlApplicationContext 入手,去看看他的繼承關係是什麼樣的。框架
若是圖片看不清楚,能夠自行在 IDEA 裏面藉助 Diagrms 功能進行查看。從圖中能夠看到,ClassPathXmlApplicationContext 一路火花帶閃電的層層繼承,最終成爲了 BeanFactory 接口的一個間接實現。因此代碼裏可使用多態將 ClassPathXmlApplicationContext 的實例賦值給 BeanFactory。ide
在繼承鏈中有一個抽象類 AbstractApplicationContext,其中重載了多個 getBean()
方法用於獲取容器內的 Bean。而這些方法無一例外的都調用了 getBeanFactory()
來先獲取一個 BeanFactory 實例,進而調用 BeanFactory 的 getBean()
方法實際執行 Bean 獲取。測試
意外的是,這個類裏的 getBeanFactory()
方法是個抽象方法。查看其返回值 ConfigurableListableBeanFactory 接口的實現,發現不管哪一個實現都是返回自身的 beanFactory
字段,而這個字段的類型都是 DefaultListableBeanFactory。this
同時,在 AbstractApplicationContext 的 prepareBeanFactory()
中也明確指定了要使用的 BeanFactory 實現是經過 getBeanFactory()
方法返回的 DefaultListableBeanFactory。spa
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); // AbstractApplicationContext 663行
複製代碼
回到最初的示例,配置文件裏指定了以 byType
類型注入的形式進行注入,那麼根據上述分析,user#beanFactory
注入的就必定是 DefaultListableBeanFactory。而經過配置文件建立的是 ClassPathXmlApplicationContext 的實例,這兩個對象天然就不相等了。代理
至於示例中的 beanFactory
等於 applicationContext
,這是由於在這個示例程序運行過程當中,只有一個 ClassPathXmlApplicationContext 是 ApplicationContext 接口的實現,因此按類型注入下二者其實就是同一個對象。
結合上面的繼承關係圖能夠看出,ClassPathXmlApplicationContext 其實是 BeanFactory 接口的一個最終實現。在其繼承鏈上,BeanFactory 被從 ApplicationContext 接口開始的多個類進行了功能豐富,而且對 BeanFactory 的基礎功能進行了代理。官方文檔這麼描述 BeanFactory 和 ApplicationContext 的關係:
In short, the
BeanFactory
provides the configuration framework and basic functionality, and theApplicationContext
adds more enterprise-specific functionality. TheApplicationContext
is a complete superset of theBeanFactory
and is used exclusively in this chapter in descriptions of Spring’s IoC container.
ApplicationContext 是 BeanFactory 的超集,BeanFactory 僅提供基礎功能和配置,ApplicationContext 在其上面增長了更多企業性功能。能夠簡單的理解爲,BeanFactory 是給 Spring 框架自身用的,而 ApplicationContext 是給 Spring 框架的使用者用的。