Spring
未读Spring系列之 探索AOP大家好,我叫Spring,是众多程序员朋友们手中把玩的宠儿。AOP,作为我体内最重要的特性之一,自从我诞生以来,已经陪伴我度过了二十多年。为了让各位程序员朋友们尽可能地减少代码量,将“懒惰”这一美德发挥到极致,我早在诞生之前,就开始了广泛的探索和学习,以求能在现有方法、属性和代码块的基础上,批量地为它们添加额外的功能。对于那些追求代码简洁的朋友们来说,AOP就像如鸟入林,如鱼得水,如虎添翼。因此,我汲取了它的精髓,进化出了属于自己的AOP机制。虽然没有AspectJ那么全面,但它完美适应了我的内部环境。这绝不是抄袭,而是借鉴和创新!
最直接的应用当然是减少重复代码。比如,去理发店剪头发,过程不仅仅是剪发那么简单,还包括排队、洗头、剪发后再次洗头、吹头、结账等环节。如果我们用代码来模拟这一场景,会发现为每个理发师(Tony、Kevin等)都编写相同的排队、洗头、吹头、结账代码是多么的冗余。聪明的我们当然不会让这种事情发生,将这些通用流程抽取成公共方法调用是个不错的解决办法。但,这真的是最“懒”的做法吗?当然不是。既然这些重复的方法每次都得调用,那么在每次调用 ...
【从零构建Spring|第五节】 加载,解析资源并注册Bean对象日志上一节我们实现了往 Bean 对象注入属性,但所有的操作都需要用户手动填写,这显然是不合适的,因此这一节我们来优化
本章节主要有以下改动:
资源加载接口的定义和实现
解析 XML 处理 Bean 注册
问题通过单元测试进行手动操作 Bean 对象的定义、注册和属性填充,以及最终获取对象调用方法。但这里会有一个问题,就是如果实际使用这个 Spring 框架,是不太可能让用户通过手动方式创建的,而是最好能通过配置文件的方式简化创建过程。需要完成如下操作:
如图中我们需要把步骤:2、3、4整合到Spring框架中,通过 Spring 配置文件的方式将 Bean 对象实例化。
接下来我们就需要在现有的 Spring 框架中,添加能解决 Spring 配置的读取、解析、注册Bean的操作。
XmlReader 的作用,就是为 Spring 自动配置 Bean 对象的注册、属性设置、Bean 对象实例化。整个过程用户无感,最终用户所需要做的操作就是调用所需的 Bean 对象就行!
设计依照本章节的需求背景,我们需要在 ...
Spring
未读Spring系列之 AOP原理篇大家好,我叫Spring,是众多程序员朋友手心的宝贝,AOP作为我体内的重要组成部分,尽管其重要性无可替代,但使用起来却相当直观和简便。我们只需创建一个类,并将其标记为切面(@Aspect),即可激活AOP的功能。在切面类中定义增强方法,使用如@After、@AfterReturning、@Around等注解来指示增强逻辑在目标方法执行的不同阶段介入。例如,@After在方法执行后触发,@AfterReturning在方法正常返回后执行,而@Around则可以完全包围目标方法。
让我们举个例子,假如我们想在某个方法执行后记录日志,只需简单地添加@After注解即可。如果想要在方法抛出异常后执行特定逻辑,则可以使用@AfterThrowing。通过这些注解,我们可以精准地针对特定类的特定方法实施增强。一旦完成了这些基本设置,AOP就可以在我的环境中发挥作用了。当原有的bean方法被调用时,相应的增强逻辑就会自动执行。
那么,AOP在我体内是如何运行的呢?当我启动时,会创建IOC容器,并对容器中的bean进行三个关键步骤:构造、属性注入、初始化。AOP的实现 ...
【从零构建Spring|第四节】 Bean的属性注入日志前几节内容,我们初步实现了一个容器、定义 Bean、注册 Bean 、实例化,按照是否包含构造函数实现不同的实例化策略。
本章节有以下变动:
查询类中是否有属性,如果类中包含属性,在实例化时注入属性信息。对于属性的填充不只是 int、Long、String,还包括还没有实例化的对象属性,都需要在 Bean 创建时进行填充操作。不过这里我们暂时不会考虑 Bean 的循环依赖,否则会把整个功能实现撑大,这样新人学习时就把握不住了,待后续陆续先把核心功能实现后,再逐步完善
设计架构图鉴于属性填充是在 Bean 使用 newInstance 或者 Cglib 创建后,开始补全属性信息,那么就可以在类 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加补全属性方法。
属性填充要在类实例化创建之后,也就是需要在 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加 applyPropertyValues 操作。
由于我们需要 ...
【从零构建Spring|第三节】 JDK和Cglib动态代理实例化策略日志在上一节中,出现了一个小问题:没法实例化有参构造对象
本章节有以下变动:
使用Cglib字节码方式、JDK内部方式进行有参对象的实例化
后续章节可采用策略模式优化策略的选择
这里不小心把下一节的 UML 画了。。。
因为比较简单,就只展示 Cglib 字节码和 JDK 两种实例化对象的代码了
Cglib方式:@SuppressWarnings({"rawtypes"})public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy { @Override public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException { Enh ...
Spring
未读Spring系列之 Bean的生命周期我叫Spring,今天为大家介绍5.x版本的我,体内最核心的运行原理之一——IOC(控制反转)中Bean的生命周期。后续将基于此一步一步拆解我的身体,为大家做更多的原理性介绍,帮大家在面试和走向架构岗位做一点点贡献。
首先程序员大哥们在我身体上编写的各种Bean, 是我的体内最为核心的东西。
Bean在我体内,会经历三个大的阶段:生产、使用、销毁。其中,以生产阶段最为复杂。在程序员命令我启动的那一刻开始,我体内的生产线就开始准备生产一个个的Bean。启动过程很复杂,下一个视频会为大家详细介绍。
在我启动之初,为了精准地了解程序员对于Bean的要求,我使用XML配置、注解扫描等各种方式,将程序员在我体内定义的Bean类一个个找到,即BeanDefinitionMap。
有了这些“Bean定义”集合之后,我就可以遍历这个集合,然后通过我体内的createBean方法,为程序员创建一个个Bean对象。
创建Bean大体分为“构造对象、填充属性、初始化实例、注册销毁”四个步骤:
首先,构造对象。我用反射机制从“Bean定义”中的BeanClass拿到这个类 ...
【从零构建Spring|第二节】 工厂, 模板方法模式优化Bean容器日志在上一节中,只是简单创建了 BeanDefinition 和 BeanFactory
本章节有以下变动:
使用单例模式注册 Bean 容器,从而实现对象第二次获取时可以从内存中获取对象
使用工厂模式将 Bean 的创建过程交给容器,而不是在调用时期传递一个实例化好的 Bean 对象
使用模板模式统一通用核心方法的调用逻辑和标准定义
设计完善 Spring Bean:注册 Register 和获取 Get
架构图
注册 Register提示
非常重要的一点是 Bean 注册时只注册一个类信息,而不会直接将实例化信息注册到 Spring 容器中,所以我们修改 BeanDefinition 中的属性 bean,将类型从 Object 转换为 Class。
负责 bean 对象第一次注册,之后存储到 单例对象缓存中,Get 直接从内存中获取
获取 Get提示
获取 Bean 对象时就需要处理 Bean 的对象实例化操作以及判断当前单例对象是否在容器里缓存起来。
定义 BeanFactory 也就是 Bean 工 ...
Spring
未读Spring系列之 IOC容器的创建我叫Spring,是一个万千程序员朋友们每天都在手心把玩的小宝贝。上次为各位朋友们介绍了我是如何通过SpringApplication.run(String[])启动,今天为大家详细介绍第四个大阶段“填充容器”,也就是面试中最频繁问到的步骤“自动装配Bean”。
这一阶段共分为12个小步骤:
第一步,我会通过prepareRefresh方法,在已有的“系统环境”基础上,准备Servlet相关的环境。其他的环境配置在第二个大阶段“环境准备”中就已经注册完成了,具体可以参考合集的第二集。这一步还包括对ServletConfig.InitParams进行赋值,然后通过validateRequiredProperties方法验证是否有必填的环境变量。最终,完成监听器和事件初始化之后,环境准备就完成了。
第二步和第三步,由于Spring Boot选择了ServletWebServerApplicationContext作为容器,在之前的步骤已经构造好了BeanFactory,因此obtainFreshBeanFactory中不进行任何处理。不过值得注意的是,对 ...
Redis最佳实践🎉 本文, 我们将深入探索 Redis,一个强大且实用的开源内存数据库 , 以键值对形式提供数据结构存储服务。
概述💾始于缓存
在常见的 Web 应用架构中,静态内容(如 HTML、CSS、JS、图片等)可通过 CDN 或 nginx 缓存;而对于数据库中的动态数据,为减轻后端数据库的压力,可利用 Redis 来缓存那些不常变更的部分。
🔒 Redis 不止于缓存
除作为缓存工具外,Redis 还能充当分布式锁的角色,确保在高并发场景下的数据一致性。此外,它还提供了丰富的高效数据结构与算法供开发者使用
📚 Redis 数据结构一览
Redis 常用的数据结构包括但不限于:
String:基本的键值对存储。
List:双向链表,支持两端插入、弹出元素。
Set:无序集合,自动去重。
Sorted Set:有序集合,每个成员带有分数属性,按分数排序。
Hash:键值对集合,适用于存储对象型数据。
💡 学习策略
面对可能略显枯燥的 Redis 命令,我们的学习策略是结合实际应用场景逐一解析,让理论知识与实践操作紧密结合,便于理解与记忆。
📢 注意 ...
Spring
未读SpringMVC扩展点
DispatchServlet:
这是Spring MVC的核心控制器,负责处理所有的HTTP请求和响应。它根据请求的URL来决定调用哪个处理器(Controller中的方法),并最终返回响应给客户端。
它使用HandlerMapping来确定具体的请求应该由哪个处理器方法来处理。
HandlerMapping:
这个接口定义了如何将HTTP请求映射到处理器方法。RequestMappingHandlerMapping是HandlerMapping的一个实现,它使用注解(如@RequestMapping)来映射URL到具体的处理器方法。
HandlerAdapter:
这个接口定义了如何调用处理器方法。RequestMappingHandlerAdapter是HandlerAdapter的一个实现,它负责调用与@RequestMapping注解的URL匹配的处理器方法。
RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter:
这两个组件是Spring MVC中处理基于注解的映射的 ...