1. 对spring 的理解
spring 是一个广泛应用于企业级java 开发的强大框架, 为开发复杂的应用程序提供了全面而高效的解决方案
1. spring 的核心是控制反转+依赖注入, 即IOC 和DI, 这意味着对象的创建和管理不再由开发者直接负责, 而是可以交由Spring 容器来处理, 通过配置文件或者注解的形式, 可以清晰的定义对象之间的依赖关系, 使得代码更加模块化,可维护和可测试
2. spring 还提供了面向切面(AOP)编程的支持, 这使得我们能够将横切关注点(如记录日志、事务管理、权限检查等) 从业务逻辑中分离出来, 以一种更加模块化和可重用的方式进行处理
比如, 对于spring 事务, 可以通过AOP定义一个切面, 在方法执行前后自动处理事务的开始和提交/回滚, 而无需在每个业务方法中重复编写事务相关代码
3. 在数据访问方面, spring 整合了多种数据访问技术, 如JDBC、MyBatis、Hibernate等, 并提供了统一的模版和资源管理, 简化了数据操作的复杂性
4. spring 的web 模块为构建web 应用提供了强大的支持, 包括控制器的定义、请求处理、视图解析等, 与其他前端的集成也非常方便
5. spring Security 则为应用提供了全面的安全管理功能, 包括用户认证、授权、加密等
6. 对于分布式系统, spring cloud 基于spring 框架, 提供了一系列的工具和组件, 用于实现服务注册与发现、配置管理、负载均衡、断路器等微服务架构的关键功能
7. 在实际项目开发中, spring 大大提高了开发效率,减少了代码的冗余,增强了系统的可扩展性和可维护性
spring6.0 提供了AOT的支持
2. 对IOC的理解
Spring 的IOC 是一种设计模式,核心思想是将对象的创建、组装和管理过程交给框架来完成,而不是由应用程序直接控制。
这种模式通过将应用程序的控制权交给框架来提高应用程序的可扩展性、灵活性和可维护性
Bean 的定义:
基于XML 的方式以及基于配置类的方式, @Component 注解
Bean 的发现
@Resources @Autowired 构造器等
3. IOC 的原理
本质上是java反射+xml 解析
IOC 本身是针对bean 的管理
bean 的定义
bean 的加载
IOC 是spring 框架的核心概念之一, 从根本上改变了对象创建和管理的方式, 传统模式中, 对象之间的依赖关系由对象自身来创建和维护, 而在IOC理念中, 这种控制被反转了,
对象的创建和依赖关系,不再由对象自身负责,而是交给一个专门的容器, 即IOC容器, IOC 容器负责创建对象、配置对象属性,并将依赖的对象注入到需要他们的对象中
在IOC模式下,依赖对象可以通过配置(XML配置文件或者注解等方式) 来进行创建
这样做,首先降低了对象之间的耦合度, 对象不在关心依赖对象的创建细节, 只需要关注自身的业务逻辑.
其次 使得代码更容易测试, 可以更方便的为对象注入模拟的依赖对象进行单元测试,同时IOC容器还可以集中管理对象的生命周期, 实现资源的优化和共享
3.1 bean 的定义
在spring 中, bean 是一个被spring 容器管理的对象,
bean 的定义通常包含了对象的各种信息, 如对象的类型,属性值、依赖关系、作用域等等
bean 可以通过 xml 配置、java 注解 如: @Component 及其派生注解 、java 配置类 等方式进行定义
bean 的定义还可以包含属性的设置、构造函数参数的注入、依赖对象的注入等配置,以满足不同的需求
3.2 bean的加载
在spring 中,对于以配置类形式进行的Bean 加载,会产生对应的BeanDefinition, 用于定义一个类的相关信息, 只要有对象关联对象信息,就会存在一个BeanDefinition
随后, 此类信息会被存储至BeanFactory(bean 工厂)。而在BeanDefinition 与BeanFactory 之间,存在着一个名为BeanDefinitionRegistry (桥梁注册器)的组件, 通过这个注册器,能够将bean 定义注册到BeanFactory 中
bean 的加载时一个复杂但有序的过程, 确保了应用程序能够正确获取和使用所需的对象
1. 首先, spring 会去读取配置信息, 可以是xml 文件, 识别其中定义的bean 元素, 对于注解方式, spring 会扫描指定的包或者类路径,查找带有相关注解的类(Component,Service 等)
2. 然后,对于有依赖关系的bean, spring 会按照依赖的顺序进行处理, 会优先加载被依赖的bean, 以确保在创建当前bean 时, 所需依赖都已经准备好
3. 在创建bean 实例时,如果是通过构造函数注入依赖,spring 会调用相应的构造函数,并传入已经准备好的依赖对象,如果是通过属性设置或者方法注入,spring 会在实例创建后进行相应的注入操作
4. 在实例创建和依赖注入完成后,spring 可能会执行一些初始化回调方法,例如实现了InitializingBean 接口的afterPropertiesSet 方法, 或者通过配置指定的初始化方法
5. 然后根据bean 的作用域, 如果是单例bean, 会将其存储在一个共享的缓存中,以便后续的请求能够直接获取, 如果是原型bean, 则每次请求都会创建新的实例
6. 在整个加载过程中, spring 还会处理一下异常情况, 例如依赖无法满足、初始化失败等,并提供相应的错误处理机制
1. 前戏, 做容器刷新前的准备工作, prepareRefresh()
2. 获取BeanFactory 对象, 完成XMl配置文件的加载解析, beanDefinition, bean 定义, obtainFreshBeanFactory()
3. BeanFactory 的准备工作, 对各种属性进行填充, prepareBeanFactory(beanFactory)
4. 交给子类扩展的方法, postProcessBeanFactory(beanFactory)
5. 调用各种beanFactory处理器, invokeBeanFactoryPostProcessors(beanFactory)
6. 注册bean处理器, 这里只是注册功能(registerBeanPostProcessors(beanFactory))
7. 为上下文初始化message 源, 即不同语言的消息体,国际化处理 ()initMessageSource
8. 初始化事件监听多路广播器 initApplicationEventMulticaster
9. 留给子类初始化其他的bean onRefresh()
10. 在所有注册的bean 中查找listenerBean 注册到消息广播器中
11. 初始化剩下的单实例 finishBeanFactoryInitialization(beanFactory)
12. 完成刷新过程, 并发出相关通知, finishRefresh
13. 为防止bean 资源占用, 在异常处理中, 销毁已经在前面过程中生成的单例bean destroryBeans
14. 重置active 标志 cancelRefresh(ex)
3.3 bean 的生命周期
1. bean 的生命周期, 整体可以囊括为 实例化、赋值、初始化、使用和销毁
2. 首先是实例化, spring 会根据配置文件或者注解等定义信息去进行创建bean 的实例
3. bean 对象创建之后, 会对其进行属性赋值, 包括通过构造函数,set方法或者字段直接注入等方式
4. 然后在初始化前, 会有一些前置处理, 可以修改属性值或者添加额外功能, 要求bean 实现了BeanPostProcessor 接口的PostProcessBefore 方法
5. 然后是通过init-method 方法或者通过InitializingBean 接口的afterPropertiesSet 方法对bean 进行初始化
6. 初始化之后对bean 的后置处理, 要求实现了BeanPostProcessor 接口的postAfter 方法
7. 之后是bean 的使用, 可以提供相应的服务或者功能
8. 最后就是当应用关闭或者不再被需要时,进入销毁阶段,如果bean 实现了Disposablebean 接口, 其destroy 方法会被调用, 如果指定了销毁方法, 也会在此时执行,以释放自由、关闭连接
4. 对AOP的理解
AOP 即面向切面编程,也可以说是OOP, 面向对象编程的补充和完善. AOP是OOP的一种方式
在代码执行过程中,动态嵌入其他代码,即叫做面向切面编程,其本质上是java动态代理在运行时,框架根据我们定义的Pointcut 和 advice, 为目标生成代理对象,
提供了一种非常优雅的方式来解决横切关注点的问题, AOP能够将这些横切关注点从业务逻辑中分离出来,集中在一个地方进行定义和管理
5. spring 的事务
5.1 jdbc 事务的概念
1. 获取连接对象
2. 获取statement 对象
3. 关闭事务自动提交
4. 增删改sql 语句的插入
5. 执行sql
6. 事务提交/回滚
String url = "";
String username = "";
String password = "";
Connection conn = null;
Statement stmt;
try {
// 创建数据库连接
conn = DriverManager.getConnection(url, username, password);
//
stmt = conn.createStatement();
// 关闭自动提交
conn.setAutoCommit(false);
String insertSql = "insert into wrk_info values()";
// 执行sql
stmt.execute(insertSql);
// 提交事务
conn.commit();
// 关闭连接
} catch (Exception e) {
if (null != conn){
try {
// 异常回滚事务
conn.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
e.printStackTrace();
} finally {
if (null != conn){
try {
// 关闭事务连接
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
5.2 spring 事务
spring 的事务是基于数据库事务的概念,通过编程式事务或者声明式事务两种方式来实现
1. 编程式事务,需要在代码中显式的控制事务的开始、提交和回滚,通过获取TransactionManage 对象,并调用相应的方法来管理事务。
这种方式灵活,但代码侵入性较高,维护起来相对复杂
2. 声明式事务,通过xml配置或者注解来定义事务的属性,如传播行为、隔离级别、超时时间等,spring 会在运行时根据这些配置自动管理事务
通过 TransactionManager 对象,获取事务的一些相关方法
通过getTransaction 来获取事务, 获取事务之后通过doBegin 来开启事务和连接, 同时会关闭事务的自动提交
通过commit 来提交事务
通过rollback 来回滚事务
声明式事务, @Transaction 注解, 其原理和上面声明式事务类似,只不过是通过aop 的形式去创建了transactionDefinition ,
通过代理的形式去创建了对应的TransactionManager
5.3 Transaction 注解如何注入到容器的
1. 首先需要在启动类中开启事务, @EnableTransactionManagement
2. 在@EnableTransactionManagement 注解中, 有一个@Impor 引入了TransactionManagementConfigurationSelector 类
3. 在对应的selectImports 中, 通过proxyTransactionManagementConfiguration 类去获取全限定类名, 用于 selectImport 注入
4.
5.4 事务的传播属性
在 spring 中, 一共存在7个事务的传播行为,分别是
1. required, 支持当前事务,没有事务时, 新建事务
2. supports, 支持当前事务,没有事务时,以非事务执行
3. mandatory, 支持当前事务,没有事务时,抛异常
4. required_new, 新建事务,存在事务则挂起
5. not_supports, 以非事务运行,存在事务则挂起
6. never, 以非事务运行,存在事务则抛异常
7. nested, 嵌套事务,存在事务嵌套事务,不存在事务新建事务
5.5 事务的隔离级别
spring 的事务隔离级别是根据数据源的隔离级别走的,
常见的隔离级别有4种,分别是读未提交,有 脏读,幻读,不可重复度问题。
读已提交,有幻读不可重复读问题
可重复读,有幻读问题
串行化,没有任何问题,只是慢
脏读: 事务读取到其他事务未提交数据
不可重复读: 事务的两次读取查询,因为另一个事务修改,导致数据不一致
幻读: 事务的多次读取查询, 数据量结果集不同
6. spring循环依赖问题
循环依赖 是指在多个实例或者类之间存在相互依赖的关系,形成一个闭环
在spring 中,循环依赖主要有 构造器注入循环依赖以及属性设值循环依赖 两种情况
其中 构造器注入循环依赖,无解, spring 只是帮我们解决了属性赋值的循环依赖问题
通过三级缓存+提前暴露,解决了 循环依赖问题
一级缓存:存储已经经历完整生命周期的bean 对象
二级缓存:存储早期暴露的bean对象,其生命周期未结束,属性还未填充完整
三级缓存:存储可以存放bean的工厂
bean 的创建包括有实例化、属性注入和初始化等, 当出现循环依赖时,spring 会先将部分创建的A对象放入三级缓存,然后去创建A对象依赖的B对象,如果在创建B对象的时候,发现其又依赖于A对象,就从三级缓存中获取部分创建的A对象并放入二级缓存,完成B对象的创建后放入一级缓存,然后继续创建A对象,此时A可以从一级缓存获取完整的B对象,完成A对象的创建并放入一级缓存
要求循环依赖的bean 必须是单例,并且不为构造器注入
7. spring mvc 处理流程
1. 客户端发起请求, 通过浏览器或者其他客户端向服务器发送http请求
2. DispatcherServlet 接收请求
3. DispatcherServlet 根据URL 通过handlerMapping 找到处理该请求的controller
4. controller 接收请求参数,并进行相应业务逻辑处理
5. 控制器在处理过程中,可能会操作数据模型,准备要返回给视图的数据
6. 控制器处理完成之后,返回一个逻辑视图名,DispactherServlet 通过 视图解析器解析视图,找到对应的实际视图
7. 获取模型中的数据, 对视图进行渲染
8. DispatcherServlet 将渲染后的视图响应给客户端
8. SpringBoot 自动装配原理
1. @SpringBootApplication 注解加在启动类上
2. 在这个注解里面,主要需要看下@EnableAutoConfiguration 注解, 这个注解, 主要用于加载各种boot-starter 下载配置项,
3. 在@EnableAutoConfiguration 中存在一个@Import 注解, 会引入一个 AutoConfigurationImportSelector 的类
4. 在这个类中,会通过 springFactoriesLoader 去load 对应配置类信息, 而这个路径所对应的地址是 META 下的spring.factories ,
5. 其会通过classLoaer 去获取对应的resources,
6. 同时其还可以load META-INF下, spring 下的 org.springframework.boot.autoconfigure.AutoCOnfiguration.imports 文件中的全限定类名
8.1 @Import 注解的作用
1. import 可以导入配置类, 通过在主配置类上使用@Import 注解, 可以导入其他配置类, 使其可以成为该主配置类的一部分,方便组织配置类,使代码更加清晰
2. 导入普通类,除了导入配置类,@Import 还可以导入普通类,可以在spring 容器中创建这些类的实例并进行管理
3. 导入importSelecor 实现类, 通过这种方式根据条件动态选择要导入的类
4. 导入importBeanDefinitionRegistrar 实现类, 通过这种方式在运行时动态注册bean 到Spring 容器中
标签:事务,依赖,对象,spring,bean,注解,相关
From: https://www.cnblogs.com/antordragon/p/18353371