前面的几篇文章我们一直围绕着 BeanFactory 分析容器的初始化和依赖注入过程,本篇我们将从 ApplicationContext 触发探究容器的高级形式。ApplicationContext 相对于 BeanFactory 扩展了许多实用功能,方便开发者的使用。二者的结构设计我们在前面的文章中已经介绍过,本篇将详细分析基于 ApplicationContext 的容器初始化和注入过程。
Spring IoC 源码解析:创建和初始化 bean 实例
到目前为止,我们已经分析了 bean 配置的解析与注册过程。经过这一系列的操作,我们编写在 XML 中的半结构化静态配置已经转换成一个个的 BeanDefinition 实例存在于容器之中,接下来就可以调用 BeanFactory#getBean 方法获取目标 bean 实例。本文我们将从 BeanFactory#getBean 方法出发,探究容器基于 BeanDefinition 创建和初始化 bean 实例的过程。
Spring IoC 源码解析:自定义标签的解析过程
Spring 中的标签分为默认标签和自定义标签两类,上一篇我们分析了默认标签的解析过程,当然在分析过程中我们也看到默认标签中嵌套了对自定义标签的解析,这是因为默认标签中可以嵌套使用自定义标签。然而,这和本篇所要讨论的自定义标签还是有些区别的,上一篇中介绍的自定义标签可以看作是 <bean /> 标签的子标签元素,而本篇所要分析的自定义标签是与 <bean /> 这类标签平级的标签。
Spring IoC 源码解析:默认标签的解析过程
上一篇我们梳理了容器初始化的整体流程,了解了一个 bean 是如何从静态配置变为一个可运行的实例的,但是对于过程中涉及到的具体细节并未进行深入探究。从本篇开始,我们将回到起点重新沿着主线走一遍,与之前不同的是,这一次我们更加关注细节。
由前面的分析我们已经大致知晓 IoC 容器在初始化期间主要分为两个阶段:加载并解析配置文件和初始化 bean 实例。本文所要介绍的对于默认标签的解析发生在加载并解析配置文件阶段,以 XML 配置为例,容器会将 XML 形式的静态配置解析成对应的 BeanDefinition 对象注册到容器中。在配置方面,Spring 为开发者提供了许多可用的标签,比如 <beans />、<bean />、<import />,以及 <alias /> 等等。这些标签统称为 默认标签 (个人觉得翻译成内置标签更加合理),同时 Spring 还允许开发者自己定义标签,方法 DefaultBeanDefinitionDocumentReader#parseBeanDefinitions 中的逻辑就是判断当前标签是默认标签还是自定义标签,并调用相应的方法对标签进行解析(实现如下),本篇我们主要分析默认标签的解析过程,对于自定义标签则留到下一篇进行讲解。
Spring IoC 源码解析:简单容器的初始化过程
本文将主要对定义在 XML 文件中的 bean 从静态配置到加载成为可使用对象的过程,即 IoC 容器的初始化过程进行一个整体的分析。在讲解上不主张对各个组件进行深究,只求对简单容器的实现有一个整体的认识,具体实现细节留到后面专门用针对性的篇章进行讲解。
首先我们引入一个 Spring 入门示例,假设我们现在定义了一个类 MyBean,我们希望利用 Spring 管理类对象。
Spring IoC 源码解析:容器的基本层次结构
控制反转(IoC: Inversion of Control)是 Spring Framework 的核心基础特性,也是面向对象程序设计中的重要原则,其目的在于降低程序之间的耦合度。控制反转一般分为 依赖注入(DI: Dependency Injection) 和 依赖查找(DL: Dependency Lookup) 两种类型,不过依赖注入应用更加广泛,所以大部分时候依赖注入等同于控制反转。
在面向对象程序设计中,对象一般用于承载和处理数据,不同对象之间的相互依赖与合作构成了我们的软件系统。设想在大型软件系统设计中,需要大量的对象通过相互依赖和交互进行合作,如果这些依赖关系由对象自己去控制和管理,那么耦合度将会非常高,不易于系统的扩展和维护。这个时候我们可以将对象的依赖关系交由 IoC 容器进行管理,将对象的新建和引用赋值等操作交由 IoC 容器统一完成,而对象只需要专心负责承载和处理数据即可。这样的设计可以降低系统在实现上的复杂性和耦合度,让系统更加灵活,满足“开闭原则”,并易于扩展和维护。
程序设计中的基本原则
在编写一个系统的时候,我们总是希望我们的系统在设计上具备较好的可维护性和可扩展性,当客户需求有变,或者需要增加新功能时,能够从容应对,而一些前人总结的设计原则可以让我们在遇到这样的情况时候,不至于被动,从而能够以尽可能小的工作量来实现客户的需求。
利用享元模式解决内存大量细粒度对象
最近在看之前一个自己写的项目代码的时候,发现之前构造的责任链像个楼梯台阶一样的堆在那里,很是影响代码的美观性,并且一条链上的七、八个对象在每次请求时都需要创建一遍,对于一个高并发的项目来说,是一笔不小的开销,于是想对这一块的代码进行优化,而享元模式刚好满足我的需求。
享元模式(Flyweight)是 以共享的方式有效地支持大量的细粒度对象 。能做到共享的关键是区分 内部状态(Internal State) 和 外部状态(External State) 。
OAuth 2.0 协议原理与实现:Token 生成策略
OAuth2.0 协议定义了授权详细流程,并最终以 token 的形式作为用户授权的凭证下发给客户端,客户端后续可以带着 token 去请求资源服务器,获取 token 权限范围内的用户资源。
对于 token 的描述,OAuth 2.0 协议只是一笔带过的说它是一个字符串,用于表示特定的权限、生命周期等,但是却没有明确阐述 token 的生成策略,以及如何去验证一个 token。RFC6749 对于 access token 的描述:
The client obtains an access token – a string denoting a specific scope, lifetime, and other access attributes.
OAuth 2.0 协议原理与实现:协议原理
OAuth 2.0 协议是一种三方授权协议,目前大部分的第三方登录与授权都是基于该协议的标准或改进实现。OAuth 1.0 的标准在 2007 年发布,2.0 的标准则在 2011 年发布,其中 2.0 的标准取消所有 token 的加密过程,并简化了授权流程,但因强制使用 HTTPS 协议,被认为安全性高于 1.0 的标准。