从源码角度来看BeanFactory和ApplicationContext的关系
大家好,我是小黑,这是年前的最后一篇推文,提前祝大家新年快乐~~
这次我们从源码角度来聊聊BeanFactory
和ApplicationContext
的关系,讲一些网上文章不曾提到的点。
官方描述
先来看一下官方文档中关于BeanFactory
和ApplicationContext
的描述。
The
org.springframework.beans
andorg.springframework.context
packages are the basis for Spring Framework’s IoC container. TheBeanFactory
interface provides an advanced configuration mechanism capable of managing any type of object.ApplicationContext
is 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.
从官方文档可以了解到:
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
。
在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
才是同一个实例对象。
从源码角度来看BeanFactory和ApplicationContext的关系的更多相关文章
- Android布局性能优化—从源码角度看ViewStub延迟加载技术
在项目中,难免会遇到这种需求,在程序运行时需要动态根据条件来决定显示哪个View或某个布局,最通常的想法就是把需要动态显示的View都先写在布局中,然后把它们的可见性设为View.GONE,最后在代码 ...
- Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签
写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...
- Spring源码学习之BeanFactory体系结构
一.BeanFactory BeanFactory是Spring IOC容器的鼻祖,是IOC容器的基础接口,所有的容器都是从它这里继承实现而来.可见其地位.BeanFactory提供了最基本的IOC容 ...
- 从源码角度深入理解Toast
Toast这个东西我们在开发中经常用到,使用也很简单,一行代码就能搞定: 1: Toast.makeText(", Toast.LENGTH_LONG).show(); 但是我们经常会遇到这 ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃
1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(二)
1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...
- 从源码角度入手实现RecyclerView的Item点击事件
RecyclerView 作为 ListView 和 GridView 的替代产物,相信在Android界已广为流传. RecyclerView 本是不会有类似 ListView 的那种点击事件,但是 ...
- 从template到DOM(Vue.js源码角度看内部运行机制)
写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(https://github.com/answershuto/learnVue)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些 ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(一)
1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...
随机推荐
- Codeforces Round #170 (Div. 1 + Div. 2)
A. Circle Line 考虑环上的最短距离. B. New Problem \(n\) 个串建后缀自动机. 找的时候bfs一下即可. C. Learning Languages 并查集维护可以沟 ...
- 2016.1.22 扩充临时表空间解决ora-01652错误
今天运行一个复杂查询时报错ora-01652 无法通过128 扩展temp段, 网上说是临时表空间大小不够,运行了脚本调整临时表空间,问题解决 alter database tempfile '/ap ...
- [转载] 使用StAX解析xml
StAX 概述 从一开始,Java API for XML Processing (JAXP) 就提供了两种方法来处理 XML:文档对象模型(DOM)方法是用标准的对象模型表示 XML 文档:Simp ...
- js 制作分页
如图所示 在html中调用方法 getpage(7, 1, 1, 'URL') 1.page.js文件 代码 function getpage(count, countPage, pageIndex, ...
- linux常用命令速记
一.命令提示符说明 1. [root@localhost ~]# root: 当前登录用户 localhost: 主机名 ~: 当前所在目录 #: 超级用户提示符($: 普通用户) 2. -rwxr- ...
- 基于 Laravel-Admin 在十分钟内搭建起功能齐全的后台模板
http://laravelacademy.org/post/6468.html 1.简介 为 Laravel 提供后台模板的项目越来越多,学院君已陆续为大家介绍过Laravel Angular Ad ...
- Vue 设置class样式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【React】 npm 常用的插件
npm install –save-dev package.json 安装环境 https://segmentfault.com/a/1190000008489881 全局 https:/ ...
- linux kdb 内核调试器
许多读者可能奇怪为什么内核没有建立更多高级的调试特性在里面.答案, 非常简单, 是 Linus 不相信交互式的调试器. 他担心它们会导致不好的修改, 这些修改给问题打了补丁 而不是找到问题的真正原因. ...
- vue-learning:27 - component - 组件三大API之二:event
组件三大API之二: event 在上一节中讲到prop单向下行数据绑定的特征,父组件向子组件传值通过prop实现,那如果有子组件需要向父组件传值或其它通信请求,可以通过vue的事件监听系统(触发事件 ...