從源碼角度來看 BeanFactory 和 ApplicationContext 的關係

  • 2020 年 1 月 16 日
  • 筆記

大家好,我是小黑,這是前年的最後一篇推文,提前祝大家新年快樂~~

這次我們從源碼角度來聊聊BeanFactoryApplicationContext的關係,講一些網上文章不曾提到的點。

官方描述

先來看一下官方文檔中關於BeanFactoryApplicationContext的描述。

The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework』s IoC container. The BeanFactoryinterface 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 WebApplicationContext for use in web applications.

https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-beanfactory

從官方文檔可以了解到:

BeanFactory介面提供了能夠管理任何類型對象的高級配置機制。

ApplicationContextBeanFactory的子介面,它增加了如下一些功能:

  • 更容易與 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();      }  }  

AnnotationConfigApplicationContextApplicationContext的一個實現類,換而言之,AnnotationConfigApplicationContext也是BeanFactory的一個實現類。

但是,運行上述程式碼,System.out.println(context == bean.beanFactory);的輸出結果為false

這是不是意味著,在容器中,ApplicationContextBeanFactory是兩個不同的實例對象呢?

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();      }  }  

AbstractApplicationContextApplicationContext的抽象實現。

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;  	}   	...  }  

總結

ApplicationContextBeanFactory的子介面,但是ApplicationContext的實例對象和BeanFactory的實例對象並不是同一個。

ApplicationContext的實現中,有一個成員變數DefaultListableBeanFactory beanFactory,所有和BeanFactory介面相關的功能都是委派給這個成員變數來實現的。

ApplicationContext實現類中的beanFactory成員變數和容器中的BeanFactory才是同一個實例對象。