写在前言

依赖反转是指依赖对象的获得被反转了。依赖控制反转的实现有很多方式,Spring中IOC容器是实现这个模式的载体,它可以在对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方法调用的依赖。这种依赖注入是可以递归的,对象被逐层注入。

通过使用IOC容器,对象依赖关系的管理被反转了,转到IOC容器中来了,对象之间的相互依赖关系由IOC容器进行管理,并由IOC容器完成对象的注入。

这里的“反转”可以认为是“责任”的反转,把责任交给了容器

在Spring中,Spring IOC提供了一个基本的JavaBean容器,通过IOC模式管理依赖关系,并通过依赖注入和AOP切面增强了为JavaBean这样的POJO对象赋予事务管理、生命周期管理等基本功能。

在Spring IOC容器的设计中,我们可以看到两个主要的容器系列:

  • 一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能;
  • 另一个是ApplicationContext应用上下文,它作为容器的高级形态而存在。应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境作了许多适配。

BeanFactory体现了Spring为提供给用户使用的IOC容器所设定的最基本的功能规范。

在这些Spring提供的基本IOC容器的接口定义和实现的基础上,Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。

BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。我们都知道,在计算机世界里,所有的功能都是建立在通过数据对现实进行抽象的基础上的。IOC容器是用来管理对象依赖关系的,对IOC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对整个BeanDefinition的处理来完成的。这些BeanDefinition就像是容器里装的水,有了这些基本数据,容器才能够发挥作用。

【1】BeanFactory

BeanFactory 是 Spring 的“心脏”。它就是 Spring IoC 容器的真面目。Spring 使用 BeanFactory 来实例化、配置和管理 Bean。

BeanFactory:是IOC容器的核心接口, 它定义了IOC的基本功能,我们看到它主要定义了getBean方法。getBean方法是IOC容器获取bean对象和引发依赖注入的起点。方法的功能是返回特定的名称的Bean。

BeanFactory 是初始化 Bean 和调用它们生命周期方法的“吃苦耐劳者”。注意BeanFactory 只能管理单例(Singleton)Bean 的生命周期。它不能管理原型(prototype,非单例)Bean 的生命周期。这是因为原型 Bean 实例被创建之后便被传给了客户端,容器失去了对它们的引用。

BeanFactory有着庞大的继承、实现体系,有众多的子接口、实现类。来看一BeanFactory的基本类体系结构(接口为主):

BeanFactory有三个二级子接口:HierarchicalBeanFactoryAutowireCapableBeanFactoryListableBeanFactory

ConfigurableBeanFactory可以被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry。

ConfigurableListableBeanFactory可以被称为四级接口/三级接口,其继承了ListableBeanFactoryAutowireCapableBeanFactoryConfigurableBeanFactory。这4级接口是BeanFactory的基本接口体系。

从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路径。在这条接口设计路径中,BeanFactory接口定义了基本的IOC容器的规范。在这个接口定义中,包括了getBean()这样的IOC容器的基本方法(通过这个方法可以从容器中取得Bean)。

而HierarchicalBeanFactory接口在继承了BeanFactory的基本接口之后,增加了getParentBeanFactory()的接口功能,使BeanFactory具备了双亲IOC容器的管理功能。

在接下里的ConfigurableBeanFactory接口中,主要定义了一些对BeanFactory的配置功能,比如通过setParentBeanFactory设置双亲IOC容器,通过addBeanPostProcessor配置Bean后置处理器等等。通过这些接口设计的叠加,定义了BeanFactory就是简单IOC容器的基本功能。

接口之下是抽象类与类的继承示意图,我们以XmlBeanFactory视角从下往上看如图。

AbstractBeanFactory–AbstractAutowireCapableBeanFactory–DefaultListableBeanFactory–XmlBeanFactory。

AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分功能。

AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额外实现了二级接口AutowireCapableBeanFactory

DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最强大的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。

最后是最强大的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些功能,使自己更强大。

public interface BeanFactory {// 用来引用一个实例,或把它和工厂产生的Bean区分开,就是说,如果一个FactoryBean的名字为
//a,那么,&a会得到那个FactoryString FACTORY_BEAN_PREFIX = "&";//五个不同形式的getBean方法,获取实例Object getBean(String name) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);// 判断bean是否存在boolean containsBean(String name);// bean是否单例boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// Bean是否为原型(多实例)boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 名称、类型是否匹配boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;// 名称、类型是否匹配boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;// 获取类型@NullableClass<?> getType(String name) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;// 根据实例名字获取别名String[] getAliases(String name);
}

BeanFactory最常见的实现类为XmlBeanFactory,可以从classpath或文件系统等获取资源。

File file = new File("fileSystemConfig.xml");
Resource resource = new FileSystemResource(file);
BeanFactory beanFactory = new XmlBeanFactory(resource);//或者如下
Resource resource = new ClassPathResource("classpath.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);

XmlBeanFactory通过Resource装载Spring配置信息冰启动IoC容器,然后就可以通过
factory.getBean从IoC容器中获取Bean了。

通过BeanFactory启动IoC容器时,并不会初始化配置文件中定义的Bean,初始化动作发生在第一个调用时。

对于单实例(singleton)的Bean来说,BeanFactory会缓存Bean实例,所以第二次使用getBean时直接从IoC容器缓存中获取Bean。

【2】ApplicationContext

如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的躯体了,ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置实现。

BeanFactorty接口提供了配置框架及基本功能,但是无法支持spring的aop功能和web应用。而ApplicationContext接口作为BeanFactory的派生,因而提供BeanFactory所有的功能。而且ApplicationContext还在功能上做了扩展,相较于BeanFactorty,ApplicationContext还提供了以下的功能:

  • MessageSource, 提供国际化的消息访问
  • 资源访问,如URL和文件
  • 事件传播特性,即支持aop特性
  • 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。

我们可以看下该接口的父类接口

如下图所示,是IOC容器另一个重要接口, 它继承了BeanFactory的基本功能, 同时也继承了容器的高级功能。其除了继承自BeanFactory子接口ListableBeanFactory 和HierarchicalBeanFactory外,还继承了MessageSource(国际化资源接口) 、ApplicationEventPublisher (应用事件发布接口)、ResourceLoader,ResourcePatternResolver(资源加载接口) 以及EnvironmentCapable 。

其子类则如下所示从ConfigurableApplicationContext--AbstractApplicationContext分为两个分支:AbstractRefreshableApplicationContextGenericApplicationContext。前者我们最熟悉的是以前使用xml配置时候的应用上下文ClassPathXmlApplicationContext,后者则是配置时代(springboot)我们常见的AnnotationConfigApplicationContext

这是第二条设计主线,是以ApplicationContext应用上下文接口为核心的接口设计。

这里涉及的主要设计接口有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到常用的WebApplicationContext或者ConfigurableApplicationContext接口。

常用的应用上下文基本都是ConfigurableApplicationContext或者WebApplicationContext的实现。在这个接口体系中,ListableBeanFactory和HiearerchialBeanFactory两个接口,连接BeanFactory接口定义和ApplicationContext应用上下文接口定义。

在ListableBeanFactory接口中,细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames接口方法;对于HierarchicalBeanFactory接口,我们在前面已经提到过。

对于ApplicationContext接口,它通过继承了MessageSource、ResourceLoader、ApplicationEventPublisher接口,在BeanFactory简单Ioc容器的基础上添加了许多对高级容器的特性的支持

【3】区别与总结

BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用 ApplicationContext。
应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

BeanFactory和ApplicationContext都支持BeanPostProcessor和BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。(Applicationcontext比 beanFactory 加入了一些更好使用的功能。而且 beanFactory 的许多功能需要通过编程实现而 Applicationcontext 可以通过配置实现。比如后处理 bean , Applicationcontext 直接配置在配置文件即可而 beanFactory 这要在代码中显示的写出来才可以被容器识别。 )

beanFactory主要是面对与 spring 框架的基础设施,面对 spring 自己。而Applicationcontex 主要面对与 spring 使用的开发者。基本都会使用 Applicationcontex 并非 beanFactory 。


我们常用的获取ApplicationContext

FileSystemXmlApplicationContext:从文件系统或者url指定的xml配置文件创建,参数为配置文件名或文件名数组,有相对路径与绝对路径。

ApplicationContext factory=new
FileSystemXmlApplicationContext("src/applicationContext.xml");ApplicationContext factory=new
FileSystemXmlApplicationContext("E:/Workspaces/myproject/Hello/src/applicationContext.xml");

ClassPathXmlApplicationContext:从classpath的xml配置文件创建,可以从jar包中读取配置文件。ClassPathXmlApplicationContext 编译路径总有三种方式:

ApplicationContext factory = new
ClassPathXmlApplicationContext("classpath:applicationContext.xml");ApplicationContext factory = new
ClassPathXmlApplicationContext("applicationContext.xml");ApplicationContext factory = new
ClassPathXmlApplicationContext("file:E:/Workspaces/myproject/Hello/src/applicationContext.xml");

XmlWebApplicationContext:从web应用的根目录读取配置文件,需要先在web.xml中配置,可以配置监听器或者servlet来实现。以前SSM工程的Spring容器就是XmlWebApplicationContext。

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listenerclass>
</listener>

或者

<servlet><servlet-name>context</servlet-name><servlet-class>org.springframework.web.context.ContextLoaderServlet</servletclass><load-on-startup>1</load-on-startup>
</servlet>

这两种方式都默认配置文件为web-inf/applicationContext.xml,也可使用context-param指定配置文件。

<context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/myApplicationContext.xml</param-value>
</context-param>

SpringBoot下则没有这些配置文件(确切说是不需要),SpringBoot自动实例化容器AnnotationConfigServletWebServerApplicationContext。

[读书笔记]Spring中BeanFactory和ApplicationContext的联系和区别相关推荐

  1. 请说明一下Spring中BeanFactory和ApplicationContext的区别是什么?

    请说明一下Spring中BeanFactory和ApplicationContext的区别是什么? BeanFactory: 是spring中比较原始,比较古老的Factory.因为比较古老,所以Be ...

  2. (转) Spring读书笔记-----Spring的Bean之配置依赖

    前一篇博客介绍了Spring中的Bean的基本概念和作用域(Spring读书笔记-----Spring的Bean之Bean的基本概念 ),现在介绍Spring Bean的基本配置. 从开始我们知道Ja ...

  3. 我的读书笔记——Spring

    我的读书笔记--Spring Bean 的三种配置方式 基于XML配置 基于注解配置 基于Java类配置 Bean定义 在Xml中通过 元素定义.如 在Bean实现类通过@compoent或者衍生类( ...

  4. Spring中SmartLifecycle和Lifecycle的作用和区别

    欢迎关注方志朋的博客,回复"666"获面试宝典 本文基于SpringBoot 2.5.0-M2讲解Spring中Lifecycle和SmartLifecycle的作用和区别,以及如 ...

  5. Spring中@Autowired、@Qualifier、@Resource的区别

    转自: Spring中@Autowired.@Qualifier.@Resource的区别_老周聊架构的博客-CSDN博客_qualifier和resource区别1.@Autowired@Autow ...

  6. Spring中BeanFactory和FactoryBean的区别

    先介绍一下Spring的IOC容器到底是个什么东西,都说是一个控制反转的容器,将对象的控制权交给IOC容器,其实在看了源代码之后,就会发现IOC容器只是一个存储单例的一个ConcurrentHashM ...

  7. Spring中 BeanFactory 与 FactoryBean 的区别

    作者:叁滴水 blog.csdn.net/qq_30285985/article/details/115433099 文章目录 前言 为什么会有FactoryBean? 通过源码深入学习Factory ...

  8. 哈佛幸福课相关积极心理学经典英文原版书籍-读书笔记(连载中)(转)

    原文地址:http://www.wisdomsnack.com/1291.html 2000年, 美国心理学家Martin Seligman 和 Mihaly Csikszentmihalyi 发起了 ...

  9. 《流畅的Python第二版》读书笔记——函数中的类型注解

    引言 这是<流畅的Python第二版>抢先版的读书笔记.Python版本暂时用的是python3.10.为了使开发更简单.快捷,本文使用了JupyterLab. 本章关注于Python在函 ...

最新文章

  1. oracle 定时器时间分区_oracle分区表按时间自动创建
  2. leetcode第一刷_Search in Rotated Sorted Array
  3. Mirantis OpenStack fuel web 安装 使用
  4. Redis 服务安装
  5. Linux学习-Jenkins安装
  6. SQL本地事务、asp.net事务、DTC
  7. 精益求精,抑或得过且过
  8. R及RStudio软件安装教程
  9. android的开机动画,设置安卓开机动画、开机logo
  10. MySQL卸载不干净问题,connector net卸不掉
  11. cmake gcc target specific option mismatch
  12. 栋的月结 | 第三回合(定期更新、动态、架构、云技术、算法、后端、前端、收听/收看、英文、书籍、影视、好歌、新奇)[含泪总结.. 憋泪分享!]
  13. 微型计算机的硬件系统主要核心软件,计算机硬件系统最核心的是什么
  14. 2018-2-13-win10-uwp-活动磁贴
  15. 二维码门禁助力于打造更智能化的出入管理-码上开门,说走就走
  16. 虚拟机VMware安装苹果系统macOS,超级详细教程,附文件下载,真教程!!
  17. SQL实现 模糊查询
  18. 微擎支付返回商户单号_微信小程序支付流程
  19. 目的地址,源地址防火墙双向nat转换
  20. Nginx Windows详细安装部署教程

热门文章

  1. c#2012开发安卓软件_2012年重要的软件开发发展
  2. 电商后台设计:商品维护
  3. 基于java斗地主设计报告_基于java实现斗地主代码实例解析
  4. 编写一个完整的矩阵向量乘法的MPI编程代码
  5. 摄影几何基础知识(1)
  6. 生成微信小程序指定页面二维码
  7. (绝对防御勒索病毒)装机员 ghost win7 Sp1 64位纯净6月版
  8. 114 Three.js实现深度遮挡的下雨特效
  9. < 每日算法 - Javascript解析:经典弹珠游戏 >
  10. FPGA串口多字节接收、解码和仿真