從源碼角度來看 BeanFactory 和 ApplicationContext 的關係
- 2020 年 1 月 16 日
- 筆記
大家好,我是小黑,這是前年的最後一篇推文,提前祝大家新年快樂~~
這次我們從源碼角度來聊聊BeanFactory和ApplicationContext的關係,講一些網上文章不曾提到的點。
官方描述
先來看一下官方文檔中關於BeanFactory和ApplicationContext的描述。
The
org.springframework.beansandorg.springframework.contextpackages are the basis for Spring Framework』s IoC container. TheBeanFactoryinterface provides an advanced configuration mechanism capable of managing any type of object.ApplicationContextis a sub-interface ofBeanFactory. It adds:
- Easier integration with Spring』s AOP features
- Message resource handling (for use in internationalization)
- Event publication
- Application-layer specific contexts such as the
WebApplicationContextfor use in web applications.
https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-beanfactory
從官方文檔可以了解到:
BeanFactory介面提供了能夠管理任何類型對象的高級配置機制。
ApplicationContext是BeanFactory的子介面,它增加了如下一些功能:
- 更容易與 Spring 的 AOP 集成
- 消息資源處理,用於國際化
- 事件發布
- 特定於應用程式層的上下文,如用於 web 應用程式的
WebApplicationContext。
源碼簡析
以下源碼基於 Spring 5.0.13 版本。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver
public interface ListableBeanFactory extends BeanFactory
從源碼可以證實到,ApplicationContext繼承了BeanFactory。
@Configurable public class Main { @Autowired BeanFactory beanFactory; public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class); Main bean = context.getBean(Main.class); // false System.out.println(context == bean.beanFactory); context.close(); } } AnnotationConfigApplicationContext是ApplicationContext的一個實現類,換而言之,AnnotationConfigApplicationContext也是BeanFactory的一個實現類。
但是,運行上述程式碼,System.out.println(context == bean.beanFactory);的輸出結果為false。
這是不是意味著,在容器中,ApplicationContext和BeanFactory是兩個不同的實例對象呢?
BeanFactory 和 ApplicationContext
在AnnotationConfigApplicationContext中有一個getBeanFactory方法。
準確來說,是org.springframework.context.support.AbstractApplicationContext#getBeanFactory。
@Configurable public class Main { @Autowired BeanFactory beanFactory; public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class); Main bean = context.getBean(Main.class); // false System.out.println(context == bean.beanFactory); // true System.out.println(context.getBeanFactory() == bean.beanFactory); context.close(); } } AbstractApplicationContext是ApplicationContext的抽象實現。
AnnotationConfigApplicationContext繼承了GenericApplicationContext,而GenericApplicationContext又繼承了AbstractApplicationContext。

image.png
在AbstractApplicationContext中,所有BeanFactory介面的實現,都是委託給了BeanFactory對象。
// AbstractApplicationContext#getBean(java.lang.Class<T>, java.lang.Object...) public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(requiredType, args); } // AbstractApplicationContext#getBeanFactory public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
getBeanFactory()是一個抽象方法用。
GenericApplicationContext實現了該抽象方法:
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { private final DefaultListableBeanFactory beanFactory; ... public final ConfigurableListableBeanFactory getBeanFactory() { return this.beanFactory; } ... } 總結
ApplicationContext是BeanFactory的子介面,但是ApplicationContext的實例對象和BeanFactory的實例對象並不是同一個。
在ApplicationContext的實現中,有一個成員變數DefaultListableBeanFactory beanFactory,所有和BeanFactory介面相關的功能都是委派給這個成員變數來實現的。
ApplicationContext實現類中的beanFactory成員變數和容器中的BeanFactory才是同一個實例對象。
