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

这次我们从源码角度来聊聊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

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才是同一个实例对象。

从源码角度来看BeanFactory和ApplicationContext的关系的更多相关文章

  1. Android布局性能优化—从源码角度看ViewStub延迟加载技术

    在项目中,难免会遇到这种需求,在程序运行时需要动态根据条件来决定显示哪个View或某个布局,最通常的想法就是把需要动态显示的View都先写在布局中,然后把它们的可见性设为View.GONE,最后在代码 ...

  2. Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签

    写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...

  3. Spring源码学习之BeanFactory体系结构

    一.BeanFactory BeanFactory是Spring IOC容器的鼻祖,是IOC容器的基础接口,所有的容器都是从它这里继承实现而来.可见其地位.BeanFactory提供了最基本的IOC容 ...

  4. 从源码角度深入理解Toast

    Toast这个东西我们在开发中经常用到,使用也很简单,一行代码就能搞定: 1: Toast.makeText(", Toast.LENGTH_LONG).show(); 但是我们经常会遇到这 ...

  5. Android -- 带你从源码角度领悟Dagger2入门到放弃

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

  6. Android -- 带你从源码角度领悟Dagger2入门到放弃(二)

    1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...

  7. 从源码角度入手实现RecyclerView的Item点击事件

    RecyclerView 作为 ListView 和 GridView 的替代产物,相信在Android界已广为流传. RecyclerView 本是不会有类似 ListView 的那种点击事件,但是 ...

  8. 从template到DOM(Vue.js源码角度看内部运行机制)

    写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(https://github.com/answershuto/learnVue)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些 ...

  9. Android -- 带你从源码角度领悟Dagger2入门到放弃(一)

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

随机推荐

  1. pip安装软件包报Could not fetch URL

    报这个错误的原因是python.org已经不支持TLSv1.0和TLSv1.1了.更新pip可以解决这个问题,但是你不能用命令 pip install --upgrade pip 做更新,因为TLS证 ...

  2. Python--day69--ORM正反向查找(外键)

    ForeignKey操作 正向查找 对象查找(跨表) 语法: 对象.关联字段.字段   示例: book_obj = models.Book.objects.first() # 第一本书对象 prin ...

  3. 2017年NOIP普及组复赛题解

    题目涉及算法: 成绩:入门题: 图书管理员:模拟: 棋盘:最短路/广搜: 跳房子:RMQ/二分答案/DP(本人解法). 成绩 题目链接:https://www.luogu.org/problemnew ...

  4. React 蚂蚁金服+ Antd 组件使用技巧

    安装antd 组件 yarn add antd -D import {  Card,Button,Table,From,Modal ,Select  } from 'antd'; .引入就可以使用了 ...

  5. UVA 11732——Trie

    解题思路: 首先我们可以发现: 1.若两个字符串A.B不相等,且它们的公共前缀为S,则它们的比较次数为:2 * len(S) + 1: 2.若两个字符串相等,设为A,则它们的比较次数为 2 * ( l ...

  6. 分析JVM动态生成的类

    总结思考:让jvm创建动态类及其实例对象,需要给它提供哪些信息? 三个方面: 1.生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知: 2.产生的类字节码必须有个一个关联的类加载器对象: 3.生 ...

  7. 如何理解springMVC?

    springMVC 工作原理? 简单理解:客户端发送请求-->前端控制器接受客户端的请求DispathServelt-->找到处理器映射HandMapping-->找到处理器hand ...

  8. RabbitMQ-Exchange交换器

    交换器分类 RabbitMQ的Exchange(交换器)分为四类: direct(默认) headers fanout topic 其中headers交换器允许你匹配AMQP消息的header而非路由 ...

  9. 计算机网络OSI模型

    一. 理想模型-OSI 7层模型 那么数据是如何传输的呢?看下图:上层的Header+DATA作为新的Data再次被封装,到达目的地后就像剥洋葱一样掐头(去尾)最终留下你所要传的数据. 各层功能详细阐 ...

  10. Java中大量if...else语句的消除替代方案

    在我们平时的开发过程中,经常可能会出现大量If else的场景,代码显的很臃肿,非常不优雅.那我们又没有办法处理呢? 针对大量的if嵌套让代码的复杂性增高而且难以维护.本文将介绍多种解决方案. 案例 ...