中getname_Spring IOC中的灵魂伴侣:BeanFactory ApplicationContext
推荐阅读:
- 手撕分布式技术:限流、通讯、缓存,全部一锅端走送给你
- 秋招面试总结:Java+并发+Spring+MySQL+分布式+Redis+算法+JVM等
- Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC
BeanFactory & FactoryBean
说起Spring中的灵魂伴侣难道不是BeanFactory与FactoryBean吗?ta们两个不仅长相相似,在面试题目中更是形影不离,成双成对。然而事实上二者的关系就像生命中的过客,只是匆匆一眼,便相忘于江湖。 不过FactoryBean并不孤单,远处的ObjcetFactory遥遥相望,本文中并不准备详细解析这两个接口,不过读者可以把他们两个理解为指定类型Bean的孵化器,我们可以通过这两个接口改变Bean的初始化行为。但是二者还是有很大区别的。
BeanFactory & ApplicationContext
日常工作中我们常常将BeanFactory称为容器,而将ApplicationContext称为上下文。不知大家究竟有没有思考过二者之间的关系。Spring Aware接口家族一文中我曾详细阐释过如何获取当前运行环境中的BeanFactory、ApplicationContext,我们不妨在代码中找寻答案。
- 配置类
package com.spring.container;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration@ComponentScan("com.spring.container")public class ContainerConfig {}
- 获取二者信息
package com.spring.container;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/** * @Author: Raphael */@Componentpublic class SpringIoc implements BeanFactoryAware, ApplicationContextAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.err.println(System.identityHashCode(beanFactory)); System.out.println(beanFactory.getClass().getName()); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.err.println(System.identityHashCode(applicationContext)); System.out.println(applicationContext.getClass().getName()); }}
- 启动类
package com.spring.container;import org.springframework.context.annotation.AnnotationConfigApplicationContext;/** * @Author: Raphael */public class MainContainer { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ContainerConfig.class); context.close(); }}
- 结果
显而易见二者不仅不是一个对象,类型都不一样。看到这里大多数人的认知已经破碎,因为潜意识中他们认为二者其实是一个事物。事实上人家甚至连继承关系都没有,直接打碎了另一波人的幻想。不信我们看看二者的UML类图。
几个容器?
敏锐的人其实已经发现了矛盾,认知中Spring的根容器应该有且只有一个才合理。但是这分明就是两个没有什么关联的对象啊。Spring官方文档如此论述二者的关系:
简而言之,BeanFactory提供了配置框架和基本功能,ApplicationContext增加了更多针对企业的功能。ApplicationContext是BeanFactory的一个完整的超集。
按照官方的解释:二者是一个包含与被包含的关系,那么在ApplicationContext中我们可以获得根容器吗? 上帝说:要有光,于是getAutowireCapableBeanFactory()就来了。
package com.spring.container;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.config.AutowireCapableBeanFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/** * @Author: Raphael */@Componentpublic class SpringIoc implements BeanFactoryAware, ApplicationContextAware { private BeanFactory beanFactory; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; System.err.println(System.identityHashCode(beanFactory)); System.out.println(beanFactory.getClass().getName()); } // 直接打印两个对象的比对结果 @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory(); System.err.println(factory.hashCode()); System.out.println(factory.getClass().getName()); System.out.println("二者相等吗: " + (factory == beanFactory)); }}
验证结果完全支持官方说明。
DefaultListableBeanFactory
官方对他如此定义:
Spring的{@link ConfigurableListableBeanFactory},{@link BeanDefinitionRegistry}的默认实现 成熟的bean工厂 基于bean定义元数据,可通过后处理器进行扩展
台前光亮的是BeanFactory,负重前行的却是DefaultListableBeanFactory,明明是三个人的电影,我却始终不能有姓名。那么DefaultListableBeanFactory的对象是何时产生的呢?一个新的问题又萦绕在我的心头。答案其实与IOC容器的初始化密不可分,我在这里不详叙了。我们只简单的剖析一下DefaultListableBeanFactory产生对象的心路历程。 我们在MainContainer中调用了如下构造方法:
public AnnotationConfigApplicationContext(Class>... annotatedClasses) { this(); register(annotatedClasses); refresh();}
因为AnnotationConfigApplicationContext继承了GenericApplicationContext,所以父类的的构造方法也会同时调用,容器对象就在此时诞生。
public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory();}
然后refresh()调用obtainFreshBeanFactory()。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); return getBeanFactory();}
getBeanFactory()是AbstractApplicationContext定义的抽象方法。又由GenericApplicationContext实现。
public final ConfigurableListableBeanFactory getBeanFactory() { return this.beanFactory;}
这里其实就是将自己构造方法产生的对象返回给AnnotationConfigApplicationContext。追踪到这一层的时候,容器对象的身世之谜才终于被我们揭开。其实ApplicationContext之所以有Beanfactory能力就是因为有关容器的操作他都委托给自己内部的容器对象了。举个例子:
public T getBean(String name, Class requiredType) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name, requiredType);}
这里实际上他并没有对此方法有详细的实现,而是通过getBeanFactory()获取自身内部的容器对象,然后交由ta实现。 现在脉络应该足够清晰了。Spring源码是设计模式的集大成者,这里其实运用的就是组合模式。
二者差异
其实官方有他们二者的总结
org.springframework.beans和org.springframework.context包是Spring框架的IoC容器的基础。BeanFactory 接口提供了一种高级配置机制,能够管理任何类型的对象。 ApplicationContext 是其子接口。
增加了以下特性:
- 与Spring的AOP功能轻松集成
- 消息资源处理(用于国际化)
- 活动发布
- 应用层特定的上下文
作者:颜如玉
链接:https://juejin.im/post/5e3ea6c16fb9a07cb427c5b4
中getname_Spring IOC中的灵魂伴侣:BeanFactory ApplicationContext相关推荐
- 请解释下Spring 框架中的IOC 容器?
Spring 中的org.springframework.beans 包和org.springframework.context 包构成了Spring 框架IOC 容器的基础. BeanFactory ...
- java spring server_Java server框架之(1):spring中的IoC
为什么需要IoC? 一般的对象耦合是在编译时确定的,也就是说当我们写如下类: 1 public classStaticCoupling { 2 3 String s = new String(&quo ...
- java spring server_java server之spring中的IOC如何用java实现?
** 什么是IOC? 一般的对象耦合是在编译时确定的,也就是说当我们写如下类: public class StaticCoupling { String s = new String("hz ...
- Spring中的IOC介绍
Spring中的IOC介绍 IOC(控制反转) IOC介绍 IOC是什么 IOC能做什么 Spring容器管理对象 1.maven管理依赖 2.给定容器的配置文件 3.IOC容器管理对象 4.通过容器 ...
- java中ioc作用_Spring中的IOC是什么意思,为什么要用IOC而不是New来创建实例?
这里是修真院后端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析后端知识/技能,本篇分享的是: [Spring中 ...
- Spring中的IOC容器原理
什么是IOC: IOC(Inverse of Control)控制反转,将对象的创建权利反转给Spring框架. 它是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度. IOC容器的底 ...
- Spring中的IoC(控制反转)和DI(依赖注入)
一.Spring IoC的基本概念 控制反转(IoC) 是一个比较抽象的概念,它主要用来消减计算机程序的耦合问题,是Spring框架的核心. 依赖注入(DI) 是IoC的另外一种说法,只是从不同的角度 ...
- 用IDEA详解Spring中的IoC和DI(挺透彻的,点进来看看吧)
用IDEA详解Spring中的IoC和DI 一.Spring IoC的基本概念 控制反转(IoC)是一个比较抽象的概念,它主要用来消减计算机程序的耦合问题,是Spring框架的核心. 依赖注入(DI) ...
- Springc中的IOC控制反转c01
一.IoC(控制反转)基本概念 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度.其中最常见的方式叫做依赖注入(D ...
最新文章
- 习题10-2 递归求阶乘和 (15 分)
- oracle不能用uuid,Oracle 应用之--VirtualBox UUID问题
- javascript +new Date()
- 用java编写打印时间_编写一个java程序,读取系统时间,然后将时间用中文输出...
- EmguCV 一些基本操作
- 蓝桥杯历届试题----矩阵翻硬币
- 测试markdown的发布
- C++学习 —— 灵活的继承特性【C++不是玩具,而是生产工具】
- python+webdriver(三)
- deap dataset的不同分类模型的实现(1)
- Log:日志选型调研『一』
- 房贷新政刺激换房需求 北京楼市成交量反弹
- 256K,320K及以上Nero AAC,QAAC,FAAC,MP3,OGG等主流有损音频格式横评
- html文档在word打开是乱码怎么解决,word打开是乱码怎么办?怎么解决
- 贝叶斯分类器,什么是朴素贝叶斯,后续为使用贝叶斯实现海量数据的邮件筛选。带源码数据集和解决思路
- 一文说清MySQL索引数据结构
- 怎样将微信热门文章采集到自己的公众号中?
- 电脑蓝屏了怎么办修复,电脑蓝屏解决修复方法
- Scrapy新手入门
- jdbc是什么(jdbc是什么设计模式)