2019独角兽企业重金招聘Python工程师标准>>>

我们先来看类图吧:

除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口.

这边主要提供了这样的三个功能: 别名管理,单例创建与注册,工厂方法FactoryBean支持.

我们来看看这些接口,类的主要职责吧:

BeanFactory Spring IOC容器的根接口

-- HierachicalBeanFactory 实现容器的继承,就是可以有父 BeanFactory

-- -- ConfigureabelBeanFactory提供factory的配置功能

AliasRegistry 定义bean name的别名管理

-- SimpleAliasRegistry 在实现别名管理接口基础上,添加一个canonicalName查找类真是名称api

SingletonBeanRegistry 提供单例注册,查询服务

-- DefaultSingletonBeanRegistry 实现单例与DisposableBean的生命周期管理(创建,维护,销毁)

-- --FactoryBeanRegistrySupport 添加工厂方式创建类FactoryBean的支持

-- -- -- AbstractBeanFactory BeanFactory的抽象实现.

也就是说这边可以分为这样几类职责:

a, 类别名管理

b, 单例生命周期管理

c, 工厂方法初始化类对应的FactoryBean

d, BeanFactory容器

BeanFactory容器的职责(BeanFactory,HierachicalBeanFactory,ConfigureableBeanFactory)在上一篇文章<Spring源码解析 - BeanFactory接口体系解读>里已经分析过,有兴趣可以看下.

我们今天主要分析其他的三个职责,如下的接口与类(顺便做目录):

1. AliasRegistry 定义bean name的别名管理

2. SimpleAliasRegistry 实现别名管理接口

3. SingletonBeanRegistry 提供单例注册,查询服务

4. DefaultSingletonBeanRegistry 实现单例与DisposableBean的生命周期管理(创建,维护,销毁)

5. FactoryBeanRegistrySupport 添加工厂方式创建类FactoryBean的支持

1. AliasRegistry 定义bean name的别名管理

提供别名的注册,查找,删除,判断定义.

看个类图就行,不用展开.

2. SimpleAliasRegistry 实现别名管理接口

这边除了实现接口定义的api,还添加了两个公共api:

批量校验别名public void resolveAliases(StringValueResolver valueResolver)和查找别名对应的原始类名public String canonicalName(String name)

这边以别名为key缓存数据.

1     /** Map from alias to canonical name */
2     private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>(16);

分析下api实现逻辑吧:

2.1 别名注册 registerAlias(String name, String alias)

2.2 删除别名public void removeAlias(String alias)

校验下,如果别名不存在报错:throw new IllegalStateException("No alias '" + alias + "' registered");

2.3 判断别名是否存在

直接使用ConcurrentHashMap的containsKey

2.4 获取别名public String getAliases(String name)

主要逻辑是加了个锁,然后是递归调用retrieveAliases,查找多层次的别名(就是查找别名的别名这些下去)

2.5 使用StringValueResolver解析类名,别名后,进行循环依赖的校验

这边使用的是StringValueResolver的接口,具体实现需要靠注入

3. SingletonBeanRegistry 提供单例注册,查询服务

这边定义的单例注册,有点门道,主要就是相对BeanFactory的api而言有点low,没有做附加的处理.

注册的时候不管注入afterPropertiesSet的初始化回调.

查找的时候不管还没初始化的单例不说,还不管别名问题,不管FactoryBean如何区分是获取FactoryBean本身还是getObject初始化的实例.

咱们一个个api分析吧.

3.1 注册单例 void registerSingleton(String beanName, Object singletonObject);

这边的实现不会再调用 初始化回调函数,如InitializingBean的afterPropertiesSet,所以这边应该接收的是完成初始化的实例

同理也不会调用销毁的回调,如DisposableBean的destroy

这跟标准的BeanFactory中注册单例是明显不同的,因为那边是会调用各种回调.

3.2 查找单例Object getSingleton(String beanName);

String getSingletonNames;

int getSingletonCount;

设计于访问手动注册的单例.

这边只会查找已经初始化完毕 的单例,有bean definition但没有实例化的这边查找不到.

这边也不会处理FactoryBean的情况(就是具体获取getObject还是factoryBean本身的区分,&),别名也需要预先转化好了来查.

3.3 判断是否保护单例boolean containsSingleton(String beanName);

只有单例已经实例化才会返回true,剩下的看3.2 查找单例的说明吧,一样的.

4. DefaultSingletonBeanRegistry 实现单例与DisposableBean的生命周期管理(创建,维护,销毁)

在SingletonBeanRegistry注册的基础上,添加单例的共享.

也支持容器关闭时,DisposableBean实例的销毁

4.1 这边注册时,通过下面四个变量来维护:

Map<String, Object> singletonObjects 缓存以bean name为key的单例实例

Map<String, ObjectFactory> singletonFactories 缓存以bean name 为key的ObjectFactory

Map<String, Object> earlySingletonObjects 用于解决单例时的循环依赖,这边缓存以bean name为key的预初始化单例

Set<String> registeredSingletons 已经注册好的单例bean name

这边singletonObjects和registeredSingletons的数据应该是同步的,只是适用于不同的场景,但他们俩跟singletonFactories 和earlySingletonObjects分别互斥,就是singletonObjects里有了,这两个肯定没有.

同时这边也有inCreationCheckExclusions和singletonsCurrentlyInCreation进行锁控制的概念.

singletonsCurrentlyInCreation缓存bean正在被初始化,这样就不能再发起初始化;

inCreationCheckExclusions 直接缓存当前不能加载的bean

这部分看个例子就,清晰了,初始化前需要先使用beforeSingletonCreation判断

这边inCreationCheckExclusions不包含beanName才会去判断singletonsCurrentlyInCreation

1     protected void beforeSingletonCreation(String beanName) {
2         if (!this.inCreationCheckExclusions.containsKey(beanName) &&
3 this.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != null) {
4 throw new BeanCurrentlyInCreationException(beanName);
5         }
6     }

4.2 管理bean的依赖问题

使用如下三个属性进行管理:

Map<String, Set<String>> containedBeanMap 依赖的bean name为key , 就是依赖类 -> 查找 被依赖的类

Map<String, Set<String>> dependentBeanMap 依赖的原始bean name为key

Map<String, Set<String>> dependenciesForBeanMap 被依赖的bean name为key

4.3 bean 销毁

这不过跟初始化类似,自行看代码比较简单.

5. FactoryBeanRegistrySupport 添加工厂方式创建类FactoryBean的支持

添加对FactoryBean的支持,就是使用工厂方法初始化类.

这里主要涉及3个新概念:FactoryBean,BeanPostProcessor和AccessController.这三个概念懂了,源码也就分析完了.

5.1 FactoryBean,通过T getObject api提供简单工厂方法,可用用于创建单例,原型模式的实例.主要用于创建过程复杂,xml配置不方便的情况.

其实这个就是使用spring的接口对简单工厂设计模式做了一个规范,方便大家在spring中配置使用.

5.2BeanPostProcessor用于bean 初始化时进行功能增强,类似web开发中的filter.

这边有两个api:

postProcessBeforeInitialization 在类初始化前调用,比InitializaingBean 的 setPropertiesSet 和 xml文件中自定义的init-method方法执行都早

postProcessAfterInitialization 类初始话后调用,在InitializaingBean 的 setPropertiesSet 和 xml文件中自定义的init-method方法之后执行

5.3AccessController jdk的安全控制,跟spring关联不大,还是度娘吧,不多写了.

在 Java 中将执行程序分成本地和远程两种,本地代码默认视为可信任的,而远程代码则被看作是不受信的。对于授信的本地代码,可以访问一切本地资源。

在应用开发中还有一些关于安全的复杂用法,其中最常用到的 API 就是 doPrivileged。doPrivileged 方法能够使一段受信任代码获得更大的权限,甚至比调用它的应用程序还要多,可做到临时访问更多的资源。

所以就出现了spring中的典型代码

 1 if (System.getSecurityManager != null) {2     AccessControlContext acc = getAccessControlContext;3     try {4         object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object> {5 public Object run throws Exception {6 return factory.getObject;7  }8  }, acc);9     }
10     catch (PrivilegedActionException pae) {
11         throw pae.getException;
12     }
13 }else {
14     object = factory.getObject;
15 }

转自:http://toutiao.com/i6260723294287168002/?tt_from=mobile_qq&utm_campaign=client_share&app=news_article&utm_source=mobile_qq&iid=3796824860&utm_medium=toutiao_android

转载于:https://my.oschina.net/hnqingping1255/blog/636430

Spring源码解析 - AbstractBeanFactory 实现接口与父类分析相关推荐

  1. Spring源码解析之-- 事务TransactionInterceptor 分析(开启事务)

    目录 一.介绍 二.TransactionInterceptor 分析 2. 流程 2.1 invoke 2.1.1 TransactionAspectSupport#invokeWithinTran ...

  2. 源码解析:Spring源码解析笔记(五)接口设计总览

    本文由colodoo(纸伞)整理 QQ 425343603 Java学习交流群(717726984) Spring解析笔记 启动过程部分已经完成,对启动过程源码有兴趣的朋友可以作为参考文章. 源码解析 ...

  3. Spring 源码解析 - Bean创建过程 以及 解决循环依赖

    一.Spring Bean创建过程以及循环依赖 上篇文章对 Spring Bean资源的加载注册过程进行了源码梳理和解析,我们可以得到结论,资源文件中的 bean 定义信息,被组装成了 BeanDef ...

  4. Spring源码解析:自定义标签的解析过程

    2019独角兽企业重金招聘Python工程师标准>>> spring version : 4.3.x Spring 中的标签分为默认标签和自定义标签两类,上一篇我们探究了默认标签的解 ...

  5. Spring源码解析【完整版】--【bilibili地址:https://www.bilibili.com/video/BV1oW41167AV】

    [本文为bilibili视频雷丰阳的Spring源码解析的完整版总结文章,其中文章前面大部分为他人博文的搬运,后面补充了其未总结的部分] 一.Java的注解 1. 注解的概念 注释:用文字描述程序,给 ...

  6. Spring源码解析-bean实例化

    Spring源码解析-bean实例化 ​ 本文介绍Spring创建 bean 过程中的第一个步骤:实例化 bean. 1. Bean实例化源码 ​ 虽然实例化Bean有多种方式(包括静态工厂和工厂实例 ...

  7. 人人都能看懂的Spring源码解析,Spring如何解决循环依赖

    人人都能看懂的Spring源码解析,Spring如何解决循环依赖 原理解析 什么是循环依赖 循环依赖会有什么问题? 如何解决循环依赖 问题的根本原因 如何解决 为什么需要三级缓存? Spring的三级 ...

  8. Spring源码解析之@Component注解的扫描

    阅读须知 Spring源码版本:4.3.8 文章中使用/* */注释的方法会做深入分析 正文 承接Spring源码解析之context:component-scan标签解析,下面就是扫描的流程: Cl ...

  9. Spring 源码解析 -- SpringWeb过滤器Filter解析

    简介 在上几篇文章中探索了请求处理相关的代码,本篇开始探索请求处理前的一些操作代码,如Filter.本篇探索Filter初始化.请求处理等相关代码. 前言 说先简单的定义相关的测试代码: 启动类: i ...

最新文章

  1. Python入门 学习笔记
  2. ABAP--关于重复行的处理
  3. 自己实现苹果安装app动画
  4. 激发你的灵感:16个精美视差效果网页设计作品
  5. 【转】QT布局QGridLayout QHBoxLayout QVBoxLayout简要分析!!
  6. 解决:elasticsearch 更新报错:The number of object passed must be even but was [1]
  7. 转载---Adaboost学习记录
  8. JS/PHP中,数组与字符串的转换,这次总算是记住了
  9. CentOS下安装Tomcat并配置JRE
  10. Mac IDA单步调试本地程序
  11. js基础-21-事件委托
  12. STM32F103基于固件库创建工程模板
  13. 经验正交函数分析(EOF)或主成分分析(PCA)在matlab上的实现及实例
  14. [项目管理]四象限时间管理法
  15. 哈罗选了个好时点上线顺风车业务,但很可能雷声大雨点小
  16. html5单位转换器,液体单位在线换算工具
  17. 我所经历的大数据平台发展史(三):互联网时代 • 上篇
  18. Android 安全分析和漏洞挖掘|工具集
  19. i.MX283开发板第一个Linux驱动-LED驱动
  20. freecodecamp上的html练习项目

热门文章

  1. 把数学函数印在T恤上却被告侵权,这位程序员怒了
  2. 抖音出现大量“三岁用户”,马化腾李彦宏都被还童
  3. 全球首次!AI研制新药物仅需18个月,李开复梁颕宇:AI医疗已突破,但只打1分...
  4. 特斯拉大半夜「见鬼」!空无一人的路上,它却看见「幽灵」秒刹车
  5. DCASE 2020权威声学比赛:腾讯多媒体实验室斩获双项指标国内第一
  6. 百度推ACE交通引擎:不仅是无人车,车路协同新基建我也包了
  7. CVPR 2020论文开源项目一页看尽,附代码论文
  8. 首个中文多项选择阅读理解数据集:BERT最好成绩只有68%,86%问题需要先验知识...
  9. Codeforces round 1083
  10. 01-利用思维导图梳理JavaSE-Java语言基础