java- 基础知识-spring(4)

简介: 基础知识

1.Spring事务失效的八大场景与原因分析

  1. 方法内的自调用:Spring事务是基于AOP的,只要使用代理对象调用某个方法时,Spring事务才能生效,而在一个方法中调用使用this.xxx()调用方法时,this并不是代理对象,所以会导致事务失效。
    a. 解放办法1:把调用方法拆分到另外一个Bean中
    b. 解决办法2:自己注入自己
    c. 解决办法3:AopContext.currentProxy()+@EnableAspectJAutoProxy(exposeProxy = true)
  2. 方法是private的:Spring事务会基于CGLIB来进行AOP,而CGLIB会基于父子类来失效,子类是代理类,父类是被代理类,如果父类中的某个方法是private的,那么子类就没有办法重写它,也就没有办法额外增加Spring事务的逻辑。
  3. 方法是final的:原因和private是一样的,也是由于子类不能重写父类中的final的方法
  4. 单独的线程调用方法:当Mybatis或JdbcTemplate执行SQL时,会从ThreadLocal中去获取数据库连接对象,如果开启事务的线程和执行SQL的线程是同一个,那么就能拿到数据库连接对象,如果不是同一个线程,那就拿到不到数据库连接对象,这样,Mybatis或JdbcTemplate就会自己去新建一个数据库连接用来执行SQL,此数据库连接的autocommit为true,那么执行完SQL就会提交,后续再抛异常也就不能再回滚之前已经提交了的SQL了。
  5. 没加@Configuration注解:如果用SpringBoot基本没有这个问题,但是如果用的Spring,那么可能会有这个问题,这个问题的原因其实也是由于Mybatis或JdbcTemplate会从ThreadLocal中去获取数据库连接,但是ThreadLocal中存储的是一个MAP,MAP的key为DataSource对象,value为连接对象,而如果我们没有在AppConfig上添加@Configuration注解的话,会导致MAP中存的DataSource对象和Mybatis和JdbcTemplate中的DataSource对象不相等,从而也拿不到数据库连接,导致自己去创建数据库连接了。
  6. 异常被吃掉:如果Spring事务没有捕获到异常,那么也就不会回滚了,默认情况下Spring会捕获RuntimeException和Error。
  7. 类没有被Spring管理
  8. 数据库不支持事务

2.Spring中的Bean创建的生命周期有哪些步骤
Spring中一个Bean的创建大概分为以下几个步骤:

  1. 推断构造方法
  2. 实例化
  3. 填充属性,也就是依赖注入
  4. 处理Aware回调
  5. 初始化前,处理@PostConstruct注解
  6. 初始化,处理InitializingBean接口
  7. 初始化后,进行AOP

3.Spring中Bean是线程安全的吗
Spring本身并没有针对Bean做线程安全的处理,所以:

  1. 如果Bean是无状态的,那么Bean则是线程安全的
  2. 如果Bean是有状态的,那么Bean则不是线程安全的

另外,Bean是不是线程安全,跟Bean的作用域没有关系,Bean的作用域只是表示Bean的生命周期范围,对于任何生命周期的Bean都是一个对象,这个对象是不是线程安全的,还是得看这个Bean对象本身。

4.ApplicationContext和BeanFactory有什么区别
BeanFactory是Spring中非常核心的组件,表示Bean工厂,可以生成Bean,维护Bean,而ApplicationContext继承了BeanFactory,所以ApplicationContext拥有BeanFactory所有的特点,也是一个Bean工厂,但是ApplicationContext除开继承了BeanFactory之外,还继承了诸如EnvironmentCapable、MessageSource、ApplicationEventPublisher等接口,从而ApplicationContext还有获取系统环境变量、国际化、事件发布等功能,这是BeanFactory所不具备的

5.Spring中的事务是如何实现的

  1. Spring事务底层是基于数据库事务和AOP机制的
  2. 首先对于使用了@Transactional注解的Bean,Spring会创建一个代理对象作为Bean
  3. 当调用代理对象的方法时,会先判断该方法上是否加了@Transactional注解
  4. 如果加了,那么则利用事务管理器创建一个数据库连接
  5. 并且修改数据库连接的autocommit属性为false,禁止此连接的自动提交,这是实现Spring事务非常重要的一步
  6. 然后执行当前方法,方法中会执行sql
  7. 执行完当前方法后,如果没有出现异常就直接提交事务
  8. 如果出现了异常,并且这个异常是需要回滚的就会回滚事务,否则仍然提交事务
  9. Spring事务的隔离级别对应的就是数据库的隔离级别
  10. Spring事务的传播机制是Spring事务自己实现的,也是Spring事务中最复杂的
  11. Spring事务的传播机制是基于数据库连接来做的,一个数据库连接一个事务,如果传播机制配置为需要新开一个事务,那么实际上就是先建立一个数据库连接,在此新数据库连接上执行sql

6.Spring中什么时候@Transactional会失效
因为Spring事务是基于代理来实现的,所以某个加了@Transactional的方法只有是被代理对象调用时,那么这个注解才会生效,所以如果是被代理对象来调用这个方法,那么@Transactional是不会失效的。

同时如果某个方法是private的,那么@Transactional也会失效,因为底层cglib是基于父子类来实现的,子类是不能重载父类的private方法的,所以无法很好的利用代理,也会导致@Transactianal失效

7.Spring容器启动流程是怎样的

  1. 在创建Spring容器,也就是启动Spring时:
  2. 首先会进行扫描,扫描得到所有的BeanDefinition对象,并存在一个Map中
  3. 然后筛选出非懒加载的单例BeanDefinition进行创建Bean,对于多例Bean不需要在启动过程中去进行创建,对于多例Bean会在每次获取Bean时利用BeanDefinition去创建
  4. 利用BeanDefinition创建Bean就是Bean的创建生命周期,这期间包括了合并BeanDefinition、推断构造方法、实例化、属性填充、初始化前、初始化、初始化后等步骤,其中AOP就是发生在初始化后这一步骤中
  5. 单例Bean创建完了之后,Spring会发布一个容器启动事件
  6. Spring启动结束
  7. 在源码中会更复杂,比如源码中会提供一些模板方法,让子类来实现,比如源码中还涉及到一些BeanFactoryPostProcessor和BeanPostProcessor的注册,Spring的扫描就是通过BenaFactoryPostProcessor来实现的,依赖注入就是通过BeanPostProcessor来实现的
  8. 在Spring启动过程中还会去处理@Import等注解
相关文章
|
4天前
|
Java 数据安全/隐私保护 Spring
Java 中 Spring Boot 框架下的 Email 开发
Java 中 Spring Boot 框架下的 Email 开发
29 2
|
4天前
|
前端开发 Java 测试技术
Java一分钟之Spring MVC:构建Web应用
【5月更文挑战第15天】Spring MVC是Spring框架的Web应用模块,基于MVC模式实现业务、数据和UI解耦。常见问题包括:配置DispatcherServlet、Controller映射错误、视图解析未设置、Model数据传递遗漏、异常处理未配置、依赖注入缺失和忽视单元测试。解决这些问题可提升代码质量和应用性能。注意配置`web.xml`、`@RequestMapping`、`ViewResolver`、`Model`、`@ExceptionHandler`、`@Autowired`,并编写测试用例。
51 3
|
2天前
|
Java 数据库连接 数据库
spring--为web(1),富士康java面试题整理
spring--为web(1),富士康java面试题整理
|
2天前
|
安全 Java 数据库
Spring boot 入门教程-Oauth2,java面试基础题核心
Spring boot 入门教程-Oauth2,java面试基础题核心
|
2天前
|
Java
Java中int[]与Integer[]相互转化的方法,java基础知识面试重点总结
Java中int[]与Integer[]相互转化的方法,java基础知识面试重点总结
|
4天前
|
消息中间件 并行计算 Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第15天】 在现代计算机编程中,多线程是一个复杂但必不可少的概念。特别是在Java这种广泛使用的编程语言中,理解并掌握多线程编程是每个开发者必备的技能。本文将深入探讨Java中的多线程编程,从基础概念到实际应用场景,为读者提供全面的理论支持和实践指导。
|
4天前
|
Java 关系型数据库 MySQL
【Java Spring开源项目】新蜂(NeeBee)商城项目运行、分析、总结
【Java Spring开源项目】新蜂(NeeBee)商城项目运行、分析、总结
15 4
|
4天前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第13天】在计算机科学中,多线程是一种使得程序可以同时执行多个任务的技术。在Java语言中,多线程的实现主要依赖于java.lang.Thread类和java.lang.Runnable接口。本文将深入探讨Java中的多线程编程,包括其基本概念、实现方法以及一些常见的问题和解决方案。
|
4天前
|
移动开发 前端开发 NoSQL
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
49 0
|
4天前
|
JSON 前端开发 Java
【JAVA进阶篇教学】第七篇:Spring中常用注解
【JAVA进阶篇教学】第七篇:Spring中常用注解