专栏首页Coder小黑从源码角度来看 BeanFactory 和 ApplicationContext 的关系

从源码角度来看 BeanFactory 和 ApplicationContext 的关系

大家好,我是小黑,这是前年的最后一篇推文,提前祝大家新年快乐~~

这次我们从源码角度来聊聊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才是同一个实例对象。

本文分享自微信公众号 - Coder小黑(gh_5c7abf11d864),作者:coder小黑

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-01-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring5 源码学习 (7) ConfigurationClassPostProcessor (下)

    ConfigurationClassPostProcessor继承了BeanDefinitionRegistryPostProcessor接口,它实现了post...

    Coder小黑
  • Spring5 源码学习 (4) refresh 方法

    接上文 Spring5源码分析(三)refresh方法 中已经讲到了refresh()中的postProcessBeanFactory(beanFactory)...

    Coder小黑
  • 真香警告!扩展 swagger 支持文档自动列举所有枚举值

    承接上篇文章 《一站式解决使用枚举的各种痛点》 文章最后提到:在使用 swagger 来编写接口文档时,需要告诉前端枚举类型有哪些取值,每次增加取值之后,不仅要...

    Coder小黑
  • 里式替换原则——面向对象程序设计原则

    Liskov于1987年提出了一个关于继承的原则“Inheritance should ensure that any property proved abou...

    海向
  • 【资讯】关注公益:一桶冰水能拯救多少人?——信息图

    风靡全球的“冰桶挑战”是为帮助渐冻人患者发起的一次公益活动,近日,这股风刮进了中国,并迅速引爆了中国的社交网络,然而在公益活动的背后,看到的更多是娱乐化的表演,...

    小莹莹
  • 网站监控脚本 - CloudFunction应用例子

    想必很多小伙伴都有自己的博客,或者做过小Web,但是自己的Web真的健康么?目前是可访问的么?网站挂没挂?这些问题小伙伴们了解么,清楚么,或者用过相关的网站监控...

    Dfounderliu
  • 【Unity3D】官方自带人物控制器研究

    5.0.0f4版本的官方自带资源包http://pan.baidu.com/s/1o8Ujrxo

    恬静的小魔龙
  • GitHub上万星:超精细的漫画上色AI,老婆画风任你选择,登上了趋势榜

    这只AI,名字叫做style2paintV4。它在GitHub摘下了一万颗星,并登上了趋势榜。

    量子位
  • GitHub上万星:超精细的漫画上色AI,老婆画风任你选择,登上了趋势榜

    这只AI,名字叫做style2paintV4。它在GitHub摘下了一万颗星,并登上了趋势榜。

    代码医生工作室
  • 【NPM库】- 0x01

    HTML 实体是一段以连字号(&)开头、以分号(;)结尾的文本。实体常常用于显示保留字符(这些字符会被解析为 HTML 代码)和不可见的字符(如“不换行空格”)...

    WEBJ2EE

扫码关注云+社区

领取腾讯云代金券