【从零构建Spring|第十四节】 自动扫描并注册Bean前言在上一章节结束之后,我们其实已经完成了 IoC 和 AOP 的全部核心内容。但是现在还需要使用 Spring.xml 进行配置。思考思考我们平时最多是怎么用 Spring 完成信息配置的?一是注解,二是 property。
为了在核心逻辑上填充一些自动化的功能,所需要的知识有:
包的扫描注册
注解配置使用
占位符属性的填充
设计为了可以简化 Bean 对象的配置,达到整个 Bean 对象的注册都是自动扫描的。最基本的元素包括:
扫描路径入口
XML 解析扫描信息
给需要扫描的 Bean 对象做注解标记
扫描 Class 对象摘取 Bean 注册的基本信息
组装 Bean 注册信息
注册 Bean 对象
除此之外再顺带解决一个配置中占位符属性的知识点,比如可以通过 ${token} 给 Bean 对象注入进去属性信息,那么这个操作需要用到 BeanFactoryPostProcessor,因为它可以处理 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 Be ...
【从零构建Spring|第十五节】 通过注解@Autowired注入属性信息前言在目前 IOC、AOP 两大核心功能模块的支撑下,完全可以管理 Bean 对象的注册和获取,不过这样的使用方式总感觉像是刀耕火种有点难用。因此在上一章节我们解决需要手动配置 Bean 对象到 spring.xml 文件中,改为可以自动扫描带有注解 @Component 的对象完成自动装配和注册到 Spring 容器的操作。
那么在自动扫描包注册 Bean 对象之后,就需要把原来在配置文件中通过 property name="token" 配置属性和Bean的操作,也改为可以自动注入。这就像我们使用 Spring 框架中 @Autowired、@Value 注解一样,完成我们对属性和对象的注入操作
本节需要添加 @Autowired、@Value、@Qualifier 等注解功能
@Autowired 默认根据类型进行 Bean 注入,因此如果有多个类型相同的 Bean 候选者,则需要指定其中一个候选者,不然 Spring 抛出异常
@Qualifier 限定描述符除了能根据名字进行注 ...
【从零构建Spring|第十二节】 基于JDK, Cglib实现AOP切面前言本章节正式从 IoC 的实现,转向关于 AOP 内容的开发。
AOP(Aspect Oriented Programming) 内容开发,意为:面向切面编程,通过预处理的方式以及运行期间动态代理实现程序功能的统一维护。AOP 也是 OOP 的延续,在 Spring 框架中是一个非常非常重要的内容,使用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得各模块之间的业务逻辑耦合度降低。
剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
举一个不太恰当的例子:可以把切面理解为用刀切韭菜,一根一根切总是有点慢,那么用手(代理)把韭菜捏成一把,用菜刀或者斧头这样不同的拦截操作来处理。而程序中其实也是一样,只不过韭菜变成了方法,菜刀变成了拦截方法。
实现 AOP 的技术,主要分为两大类: ...
【从零构建Spring|第十一节】 观察者模式实现容器事件及监听器Spring 为什么需要事件,可以用来干什么?用来解耦代码。高内聚,低耦合的设计思想
可以用于处理日志监控和各种事件发布订阅的客制化定义
观察者模式在开发中,有很多利用到解耦的场景,例如在注册事件完成后异步发送事件推送消息,用户下单后异步发送MQ消息给与用户后续业务的跟进情况,用户付完款后就可以发送货物派送进度,都是依靠事件订阅和发布以及MQ消息这样的组件,来处理系统之间的调用解耦,最终也通过解耦的方式来提升整体系统架构的稳定性和负载能力
其实解耦思想就是观察者模式的一种体现。当对象间存在一对多关系时,则适合使用观察者模式,它定义了对象之间的一种一对多依赖关系。当一个对象的状态改变时,所有依赖他,与他有关的对象都会得到通知并且自动更新。
观察者模式角色Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具 ...
【从零构建Spring|第十节】 Aware感知容器Spring 为什么需要事件,可以用来干什么?用来解耦代码。高内聚,低耦合的设计思想
可以用于处理日志监控和各种事件发布订阅的客制化定义
观察者模式在开发中,有很多利用到解耦的场景,例如在注册事件完成后异步发送事件推送消息,用户下单后异步发送MQ消息给与用户后续业务的跟进情况,用户付完款后就可以发送货物派送进度,都是依靠事件订阅和发布以及MQ消息这样的组件,来处理系统之间的调用解耦,最终也通过解耦的方式来提升整体系统架构的稳定性和负载能力
其实解耦思想就是观察者模式的一种体现。当对象间存在一对多关系时,则适合使用观察者模式,它定义了对象之间的一种一对多依赖关系。当一个对象的状态改变时,所有依赖他,与他有关的对象都会得到通知并且自动更新。
观察者模式角色Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态 ...
【从零构建Spring|第九节】 对象作用域和FactoryBeanFactoryBean
FactoryBean是一个工厂Bean,它使用到工厂方法模式,可以代理生成一个实例
为什么使用FactoryBean在之前的设计中, Spring IoC 容器通过反射或字节码增强的方式实例化 Bean,但有些情况下,实例化较复杂,要往 xml 里 <bean> 填写大量的配置信息,且过程不能为用户支配。就像我们之前的实现,要注册 UserService,还要在 xml 配置内部的 UserDao,万一以后又多了一个 EventDao 了呢?当需要往 xml 配置里塞的东西越来越多,本来简单的操作,也会变成庞大,难以理解的屎山。
FactoryBean 很好的解决了这一点,它是一个对用户暴露的客制化 Bean 实例化的接口,用户可以通过实现该接口定制实例化Bean的逻辑。可以隐藏实例化一些复杂Bean的细节。给上层应用带来便利。说人话就是,将一个待实例化的 bean 内部所有自定义类型都丢到 FactoryBean 代理。
将对象交由Spring管理的方式:
使用XML配置 ...
【从零构建Spring|第八节】 Aware感知容器前言为什么需要 Aware?
Aware 能将业务代码和框架功能解耦,本质上就是自定义 Bean 后置处理器,在框架类代码中可以用来暴露自己的内部成员。类似这样的设计在很多框架中都有体现,用于给外部做扩展。
Spring 依赖注入的最大特点就是所有Bean 对象 对于 Spring 容器的存在是无感知的。但是在实际项目中,我们还是要用到 Spring 容器内部所提供的资源(通过 Bean 调用 Spring 容器组件资源)
举个实际案例,以下内容是我询问 chatgpt 所得到的回答。
Q:
请举一个使用 bean 需要知道 Spring 容器的案例,以证明 Aware 接口的必要性
A:
一个典型的案例是使用 ApplicationContextAware 接口,该接口使得我们能够在 Bean 中直接获取 Spring 容器,从而实现更高级别的操作。
举个例子,假设我们需要在一个自定义的 Bean 中使用 Spring 容器中的某些资源(如Bean、Properties文件等),如果不使用Aware接口,我们通常需要手动创建一个Be ...
【从零构建Spring|第七节】 注册虚拟机钩子, 实现Bean初始化及销毁日志重点:客制化 Bean 初始化阶段,用于接口暴漏、数据库数据读取、配置文件加载,链接注册中心暴露 RPC 接口以及在 Web 关闭时执行链接断开,内存销毁
目的:把这些操作交给 Spring 容器自动化处理,即满足用户可以在 xml 中配置初始化和销毁的方法,也可以通过实现类的方式处理,比如我们在使用 Spring 时用到的 InitializingBean, DisposableBean 两个接口。 其实还可以有一种是注解的方式处理初始化操作,不过目前还没有实现到注解的逻辑,后续再完善此类功能。
设计:初始化、销毁的生命周期在 Bean 加载以及注册阶段,如图所示
设计
适配器模式销毁方法有两种甚至多种,目前有 实现接口 DisposableBean、配置信息 destroy-method 两种方式。销毁方法是交由 ApplicationContext 应用上下文在注册虚拟机钩子后,虚拟机关闭前执行的操作动作。在销毁执行时,不希望 Spring 还得关注要销毁哪些类型的方法。它的使用更希望有一个统一的 ...
Spring系列之 SpringBoot启动流程我叫Spring,今天为大家介绍我体内最核心的运行原理之一——Spring Boot的启动原理,帮助大家在面试和走向架构岗位的路上做出一点点贡献。各位程序员朋友们想要启动我,这个过程本质上是由@SpringBootApplication注解驱动的,它实际上是@ComponentScan、@EnableAutoConfiguration和@Configuration这三个注解的组合。
@EnableAutoConfiguration是最为核心的部分,有了它之后,在启动时会导入“自动配置AutoConfigurationImportSelector类,这个类会将所有符合条件的@Configuration配置加载进容器。也就是说,这个类被标记为配置类,会被加载到容器中。如果启动类中不需要增加额外的配置内容,也不需要指定扫描路径,那么可以仅使用@EnableAutoConfiguration替代@SpringBootApplication,同样可以完成启动。
run()这个方法开始执行后,会经历如下四个阶段:“容器创建”、“填充容器”,所谓的“服 ...
【从零构建Spring|第六节】 应用上下文, 自动识别, 资源加载, 扩展机制的实现前言提示
说到spring容器,有的同学可能知道指的是BeanFactory,有的可能说是ApplicationContext,其实这二者都是容器类。
BeanFactory是底层基础类,位于spring-beans模块中,而ApplicationContext位于spring-context模块,是对BeanFactory的装饰,即包含一个BeanFactory实例。
ApplicationContext 本质上还是调用了 BeanFactory 内部的系列方法实现功能,并拓展了许多别的功能
日志在手写 Spring 框架过程中,需要不断扩展新的功能,如一个 Bean 的定义和实例化过程前后,是否可以做到支持自定义扩展,能够对 Bean 对象执行一些修改、增强、记录操作?要做到能随时扩展新功能,本身架构就必须设计好,不能把代码写死、耦合
本章节有所改动的内容:
合并获取 BeanFactory、读取配置、注册 Bean 等操作,合并到 Spring 框架上下文中。让面向 Spring 的组件 D ...