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

你們好,我是小黑,這是年前的最後一篇推文,提早祝你們新年快樂~~html

此次咱們從源碼角度來聊聊BeanFactoryApplicationContext的關係,講一些網上文章未曾提到的點。java

官方描述

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

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:spring

  • Easier integration with Spring’s AOP featuresapp

  • Message resource handling (for use in internationalization)
  • Event publication
  • Application-layer specific contexts such as the WebApplicationContext for use in web applications.ide

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

從官方文檔能夠了解到:this

BeanFactory接口提供了可以管理任何類型對象的高級配置機制。code

ApplicationContextBeanFactory的子接口,它增長了以下一些功能:htm

  • 更容易與 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纔是同一個實例對象。

相關文章
相關標籤/搜索