探秘 ThreadLocal 的实现内幕与小地雷

Java 多线程类库对于共享数据的读写访问主要采用锁机制来保证线程安全,而本文所要探究的 ThreadLocal 则采用了一种完全不同的策略,它不是用来解决共享数据的并发访问问题的,ThreadLocal 让每个线程都将目标数据复制一份作为线程私有,后续对于该数据的操作都是在各自私有的副本上进行,线程之间彼此相互隔离,也就不存在竞争问题。 下面的例子演示了 ThreadLocal 的典型应用场景,在 jdk 1.8 之前,如果我们希望对日期和时间进行格式化操作,则需要使用 SimpleDateFormat 类,而我们知道它是是线程不安全的,在多线程并发执行时会出现一些奇怪的问题,而对于该类使用的最佳实践则是采用 ThreadLocal 进行包装,以保证每个线程都有一份属于自己的 Sim...

阅读全文

Spring MVC 源码解析:跟踪一次简单的请求处理过程

上一篇我们分析了 web 环境下容器的初始化过程,探究了在 web 项目启动过程中,Spring MVC 所执行的一系列初始化工作,本篇中我们将一起来跟踪一次 Spring MVC 对于请求的具体处理过程,从整体上对 Spring MVC 的逻辑处理进行感知,先把握整体,后追究细节。 我们定义的控制器方法很简单,接收请求参数,然后记录到 Model 中并回显到页面上,实现如下: 123456789// http://localhost:8080/demo/hello?name=zhenchao@RequestMapping("/hello")public ModelAndView hello(@RequestParam("name") String name) { lo...

阅读全文

Spring MVC 源码解析:Web 环境下容器的初始化过程

Spring MVC 是目前最流行的 java web 框架(之一),是对传统 servlet 的高级封装,以提升 servlet 的灵活性和易用性。从广义上来说,Spring MVC 的执行过程可以分为 容器初始化 和 请求响应处理 两大部分,前者在 servlet 容器启动过程中完成,为后者的执行提供基本的运行环境,而后者则是 Spring MVC 的核心所在,负责接收请求到最终返回响应数据的复杂处理过程。 本篇章我们一起来探究 Spring MVC 在 web 环境下的容器初始化过程。Spring MVC 是建立在 Spring 基础组件之上的 MVC 框架,之前我们在分析 IoC 实现的时候,对于传统的容器初始化触发条件都是采用类似下面的方式: 1ApplicationCont...

阅读全文

Spring IoC 源码解析:循环依赖的探测与处理

Spring 为开发人员提供了极其灵活和强大的配置使用方式,在方便开发的同时也为容器的初始化过程带来了不确定性,本篇所要介绍的循环依赖就是其中之一,尤其在一些大型项目中,循环依赖的配置往往是我们不经意而为之的,幸好 Spring 能够在初始化的过程中探测到对象之间的循环依赖,并能够在一定程度上对其进行处理。 一. 什么是循环依赖以最简单的循环依赖举例,假设我们定义了两个类 A 和 B,如下: 123456789101112131415public class A { private String name; private B b; public A() { } public A(B b) { this...

阅读全文

Spring IoC 源码解析:高级容器的初始化过程

前面我们一直在以 BeanFactory 作为出发点探究容器的初始化和依赖注入过程,不过 Spring 为我们提供了更加高级的接口 ApplicationContext 可供使用,这也是在大众场景中官方推荐的使用方式。ApplicationContext 相对于 BeanFactory 扩展了许多实用功能,方便开发者的使用,二者的结构设计我们也在前面的文章中进行了专门的讲解,本篇我们一起来详细探究一下基于 ApplicationContext 的容器初始化和注入过程,至于 ApplicationContext 的使用方式,广大开发者应该是信手拈来,这里还是简单的举例一下: 123ApplicationContext context = new ClassPathXmlApplicati...

阅读全文

Spring IoC 源码解析:bean 实例的创建与初始化

到上一篇为止,我们完成了对于 bean 配置进行解析和注册过程的探究,经过这一过程我们编写在 XML 中的半结构化配置已经成为一个个的 beanDefinition 实例存在于容器之中,接下来就可以通过 getBean 的方式获取我们期望的 bean 实例,本篇中我们将继续探究从发出 getBean 指令到获取到对应 bean 实例的详细过程。 Spring 提供了多种重载和覆盖版本的 getBean 方法,当我们在执行 beanFactory.getBean("myBean") 时,我们实际上是在调用 AbstractBeanFactory 中的实现: 123public Object getBean(String name) throws BeansExcept...

阅读全文

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

Spring 中的标签分为默认标签和自定义标签两类,上一篇我们探究了默认标签的解析过程,当然在阅读源码的过程中我们也看到默认标签的解析过程中嵌套了对自定义标签的解析,这是因为默认标签中可以嵌套使用自定义标签,但是这和本篇所要讨论的自定义标签还是有些区别的,上一篇中介绍的自定义标签可以看做是 标签的子标签元素,而本篇所指的标签是与 这类标签平级的自定义标签。 一. 自定义标签的定义和使用方式在具体开挖源码之前,我们还是来回忆一下自定义标签的定义和使用方式,整体上与上一篇 1.2 小节所定义的方式类似,但还是有些许差别。要自定义标签,分为 5 步: 创建标签实体类 定义标签的描述 XSD 文件 创建一个标签元素解析器,实现 BeanDefinitionParser 接口 创建一个 ...

阅读全文

Spring IoC 源码解析:默认标签的解析过程

上一篇中梳理了 bean 加载的整体过程,但是对于过程中涉及到的具体细节没有进行深入探究,我们顺着调用链一层层往下走,最终找到了位于 DefaultBeanDefinitionDocumentReader 类中真正解析配置的方法:parseBeanDefinitions(root, delegate),本篇我们将从这里开始继续向下探索,去追寻解析的具体过程。 Spring 为开发者提供了许多配置用的标签,比如 beans、bean、import、alias 等,这些标签统称为 默认标签(个人觉得翻译成内置标签更加合理),同时 Spring 还支持开发者自己定义标签,parseBeanDefinitions 方法中的逻辑就是判断当前标签是默认标签还是自定义标签,并调用相应的方法对标签进行...

阅读全文

Spring IoC 源码解析:简单容器中 bean 的加载过程初探

本篇将对定义在 XML 文件中的 bean 从静态配置到成为可使用对象的过程,即 bean 的加载和初始化过程进行一个整体的梳理,不去深究,点到为止,只求对简单容器的实现有一个整体的感知,具体实现细节留到后面用针对性的篇章进行讲解。 首先我们来引入一个 Spring 入门使用示例,假设我们现在定义了一个类 org.zhenchao.framework.MyBean,我们希望利用 Spring 管理类对象,这里我们采用 Spring 经典的 XML 配置文件形式进行配置: 123456789<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/b...

阅读全文

Spring IoC 源码解析:容器的基本结构设计

IoC(Inversion of Control),即控制反转,是 Spring 的两大基础特性之一,也是面向对象程序设计中的重要法则,其目的是用来降低程序之间的耦合度。控制反转一般分为两种类型,依赖注入(Dependency Injection,简称 DI) 和 依赖查找(Dependency Lookup),不过依赖注入应用更加广泛,所以大部分时候依赖注入等同于控制反转。 在面向对象程序设计中,对象一般用于承载和处理数据,不同对象之间的相互依赖、合作构成了我们的软件系统。设想在大型系统设计中,需要大量的对象通过相互依赖来实现需求,如果这些依赖关系由对象自己去控制和管理,那么耦合度将会很高,不易于系统的扩展和维护,这个时候我们可以将对象的依赖关系交给 IoC 容器进行管理,将对象的新...

阅读全文

Powered by hexo & Theme by hiero   Copyright © 2015-2018 浙ICP备 16010916  号,指 · 间 All Rights Reserved.