去年通过实际框架代码的阅读,以及结合《Spring源码深度解析》和《Spring技术内幕》的阅读,对Spring框架内Bean模块有了一个整体性的认识。对此进行的总结性整理和回顾。

一、Spring IOC容器简述

如果将对象相关合作对象的引用或依赖关系的管理直接有具体对象来完成,这样会导致代码的高度耦合性和可测试下的降低。也就是说如果相关合作的引用的对象直接在某一个具体的对象之中进行硬代码不利于合作对象

之间的耦合。 如果将合作对象的引用或者依赖关系交由第三方组件(也就是Spirng IOC容器)来管理对象合作对象的引用和依赖关系的管理(通过依赖注入实现)。这样维护对象间依赖关系的控制权就转移至框架当中,降

低了对象之间的耦合度(也就是控制反转)。

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

DefaultListableBeanFactory.java

/** Map of bean definition objects, keyed by bean name */
//已经完成注册加载的Bean即容器持有载入的BeanDefinition private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

二、Spring IOC容器的结构

Spring框架针对不同的使用场景提供多个不同的功能各异的容器供用户选择和使用。BeanFacotry是IOC容器的最基本形式,其派生出了不同使用场景下的更加高级的IOC容器。

Spring IOC容器是什么实现的?

BeanFactory接口定义了获取Bean及Bean 的各种属性,提供了最基本的IOC容器的功能,是所有容器的基类。Spring框架根据不同的开发场景分别提供了不同的容器包括ApplicationContext、XmlBeanFactory、

ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext等。

(1)容器的层次结构

1) BeanFactory –>HierarchicalBeanFactory  –>  ConfigurableBeanFactory

HierarchicalBeanFactory接口继承了BeanFactory之后,增加了getParentBeanFactory()的接口功能,是BeanFactory具备了双亲IOC容器的管理功能

ConfigurableBeanFactory接口主要定义了一些对BeanFactory的配置功能

2)BeanFactory  –>AutowireCapableBeanFactory

AutowireCapableBeanFactory 接口扩展BeanFactory接口增强了自动装配的功能

3)BeanFactory  -> ListabaleBeanFactory

ListabaleBeanFactory接口扩展BeanFactory接口,提供所有bean 实例的枚举,不再需要客户端通过一个个bean name查找

4)BeanFactory –>HierarchicalBeanFactory    –>  ConfigurableBeanFactory

–>AutowireCapableBeanFactory

–>ListabaleBeanFactory

–>ConfigurableListableBeanFactory     –>DefaultListableBeanFactory   ->AbstractAutowireCapableBeanFactory  ->AbstractBeanFactory

ConfigurableListableBeanFactory接口:继承了ConfigurableBeanFactory 接口,AutowireCapableBeanFactory接口,ListabaleBeanFactory接口 ,提供了对bean定义的分析和修改的便利方法,同时也提供了对单例的预实例化

DefaultListableBeanFactory接口:

AbstractAutowireCapableBeanFactory接口:

AbstractBeanFactory接口:

5)BeanFactory –>HierarchicalBeanFactory

–>AutowireCapableBeanFactory

–>ListabaleBeanFactory

–>ApplicationContext     –>WebApplicationContext

ApplicationContext接口:

WebApplicationContext接口:

6)FileSystemXmlApplicationContext

FileSystemXmlApplicationContext接口:是一个支持XML定义的BeanDefinition的ApplicationContext,并且可以指定以文件形式的BeanDefinition的读入,这些文件可以使用网络路径和URL定义来表示。

7)ClassPathXmlApplicationContext

ClassPathXmlApplicationContext接口:一个从Class路径读取BeanDefinition定义文件的ApplicationContext

(2)容器内部的结构和表示

1)Bean的表示(Bean在容器内的抽象,即Bean标签的表示)

Spring内Bean是如何表示的?

BeanDefinition是对我们所定义的Bean的抽象,Spring框架通过它来管理基于Spring 的应用中的各种对象以及它们之间的相互依赖关系。简单的说BeanDefinition就是对象依赖关系的抽象。

BeanDefinitionHolder接口:持有一个BeanDefinition,并持有该BeanDefinition的所有别名(alias)

AliasDefinition接口:对应于alias标签的

ImportDefintion接口:对应于import标签

在Spring中BeanDefinition存在三种实现:RootBeanDefition、ChildBeanDefition、GenericBeanDefition 三者均继承于AbstractBeanDefition

RootBeanDefition类表示嵌套bean内的父<bean>,而ChildBeanDefition表示子<bean>

2)Bean配置文件的读取(Resource到Document)

3)Bean标签的解析(创建AbstractBeanDefinition)

4)Bean标签的注册

Spring将配置文件内的<bean>转化为容器的内部表示BeanDefiniton后将其注册到BeanDefinitionRegistry

BeanDefinitionRegistry接口:就像是Spring配置信息的内存数据库,主要以map的形式保存,后续操作直接从BeanDefinitionRegistry读取配置信息

5)Bean的初始化和加载

三、容器的实现过程(初始化过程)

BeanFactory bf=new XmlBeanFactory(new ClassPathResource(“test.xml”));

MyBean myBean=(MyBean)bf.getBean(“myBean”);

1、Resource 资源文件的抽象

2、加载配置文件(从Resource到Document)

从指定的配置资源路径(“test.xml”)加载配置文件,并将获取到的文件输入流转换为XML文档格式(即创建Document对象),也就是从根据指定路径的ClassPathResource对象(Resource)加载配置文件并将配

置文件转换为Document对象.

3、解析填充BeanDefinition

把配置文件转换为Document后,就需要从Document中提取各个定义的标签进行解析并将其注册到Spring IOC容器内(即添加到beanDefinitionMap 内)。 需要解析的标签有: bean标签、 alias标签、 import标

签、 beans标签、自定义标签,标签的解析过程也是创建BeanDefinition设置属性值的过程.

(1)bean标签的解析

(2)import标签的解析

(3)alias标签的解析

(4)beans标签的解析

(5)自定义标签的解析:

4、加载Bean

Bean在Spring同一个容器内只会被创建一次,后续再获取bean则直接从单例缓存中尝试获取,如果没有获取到则再次从单例工厂中(singletonFactories)加载。

(1)尝试从缓存中获取

(2)获取单例Bean

5、创建Bean

(待续)

6、容器的功能扩展

(待续)

Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)的更多相关文章

  1. CI框架源码阅读笔记5 基准测试 BenchMark.php

    上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...

  2. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...

  3. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

  4. CI框架源码阅读笔记2 一切的入口 index.php

    上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...

  5. CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程

    最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动.最近项目少,总算是有了一些时间去写一些东西.于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时 ...

  6. Spring事务源码阅读笔记

    1. 背景 本文主要介绍Spring声明式事务的实现原理及源码.对一些工作中的案例与事务源码中的参数进行总结. 2. 基本概念 2.1 基本名词解释 名词 概念 PlatformTransaction ...

  7. CI框架源码阅读笔记8 控制器Controller.php

    最近时间有些紧,源码阅读系列更新有些慢.鉴于Controller中代码比较少,本次Blog先更新该文件的源码分析. 在经过路由分发之后,实际的应用Controller接管用户的所有请求,并负责与用户数 ...

  8. 干货分享之Spring框架源码解析01-(xml配置解析)

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea Spring 是一个工厂,是一个负责对象的创建和维护的工厂.它给我 ...

  9. Spring框架源码干货分享之三级缓存和父子工厂

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 建议:学习过程中要开着源码一步一步过 Spring中对象的创建宏观 ...

随机推荐

  1. php 删除cookie有效方法

      php 删除cookie有效方法关于删除cookie的说明开始----- bool setcookie ( string name [, string value [, int expire [, ...

  2. 带你Python入门,踏进人工智能领域

    1.Python能做什么? 不知大家 没有看<中国好声音>呢?有位选择就是利用AI改编了一首周杰伦的歌<止战之殇>. Python适合做人工智能AI吗? 很明确的告诉你,可以! ...

  3. git批量恢复所有删除的文件

    git ls-files -d | xargs -i git checkout {}

  4. (9) MySQL主主复制架构使用方法

    一. 回忆主从复制的一些缺点 上节说到主从复制的一些问题 我们再来回忆一下 主从复制,增加了一个数据库副本,从数据库和主数据库的数据最终会是一致的 之所以说是最终一致,因为mysql复制是异步的,正常 ...

  5. Vue自用axios封装

    [本文出自天外归云的博客园] 这是我的Vue项目中的request.js文件,请求报错了看console就会有具体请求信息,方便调试.分享一下. 其中用到了axios和element-ui的组件,ax ...

  6. AICODER官方小程序和公众号上线了

    小伙伴们,新年好. 在新的一年里,AICODER将继续为大家提供优质的视频资源,为大家提供一个优质的问题解答平台,并且开始提供优质的职业提升类的优质培训资源. 感谢各位一直以来的支持和关注.请加一下A ...

  7. 【Unity】通用的Debugger日志模块

    模块代码整理自 http://gad.qq.com/lore/catalog/10007 Debugger类.提供打印日志的静态方法. using System; using System.IO; n ...

  8. go语言调用append之后是否重新分配内存?

    查看tidb源代码:::util/charset/charset.go,下面有段代码: // GetAllCharsets gets all charset descriptions in the l ...

  9. Ubuntu 16.04设置开机启动脚本的方法

    需求:公司卡片机容量太小,只有100G,由于使用的人比较的多,开机使用后有时候就会出现磁盘空间占满数据写不进去的情况,影响工作进度,而且每次使用完都得关掉卡片机,所以就有必要写个清理磁盘的脚本,当卡片 ...

  10. tensorflow冻结变量方法(tensorflow freeze variable)

    最近由于项目需要,要对tensorflow构造的模型中部分变量冻结,然后继续训练,因此研究了一下tf中冻结变量的方法,目前找到三种,各有优缺点,记录如下: 1.名词解释 冻结变量,指的是在训练模型时, ...