Spring 面试题

 今年环境越来越难了, 准备了一些面试题分享一下,持续更新中!着急的可看最后,

1. 谈谈你对Spring的理解

可以从2个层面理解Spring:

  • 首先Spring是一个生态:可以构建企业级应用程序所需的一切基础设施
  • 但是,通常Spring指的就是Spring Framework,它有两大核心:
  1. IOCDI 的支持

        Spring 的核心就是一个大的工厂容器,可以维护所有对象的创建和依赖关系,Spring 工厂用于生成 Bean,并且管理 Bean 的生命周期,实现高内聚低耦合的设计理念。

      2. AOP 编程的支持

        Spring 提供了面向切面编程,面向切面编程允许我们将横切关注点从核心业务逻辑中分离出来,实现代码的模块化和重用。可以方便的实现对程序进行权限拦截、运行监控、日志记录等切面功能。

        3. 其他

        除了这两大核心还提供了丰富的功能和模块, 数据访问、事务管理、Web开发等。数据访问模块提供了对数据库的访问支持,可以方便地进行数据库操作。事务管理模块提供了对事务的管理支持,确保数据的一致性和完整性。Web开发模块则提供了构建Web应用程序的工具和框架,简化了Web开发的过程。

总结一句话:它是一个轻量级、非入侵式的控制反转 (IoC) 和面向切面 (AOP) 的容器框架。

2. Spring有哪些缺点

当然,Spring作为一个广泛使用的Java开发框架,也有一些缺点。以下是一些常见的Spring框架的缺点:

  1. 学习曲线较陡峭
  2. 配置复杂
  3. 运行时性能
  4. 过度依赖
  5. 文档和社区支持

需要注意的是,这些缺点并不意味着Spring框架不好,而是在使用过程中需要注意和克服的问题。同时,Spring框架的优点和功能远远超过了它的缺点,因此它仍然是一个非常受欢迎和广泛使用的框架。

3. Spring中Bean是线程安全的吗

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

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

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

4. 谈谈你对IOC和DI的理解

IOC 控制反转 是一种软件设计思想,用于降低程序代码之间的耦合度并提高可维护性和可重用性。在传统的程序设计中,对象通常主动创建并管理它们所依赖的其他对象,这种方式导致代码高度耦合,难以测试和维护。控制反转的概念引入了一个中间层,即IoC容器,来负责对象的创建和管理它们之间的依赖关系。

IoC容器充当对象之间的“中介”,负责对象的实例化和依赖关系的注入。这意味着,而不是由对象自己创建和管理它们所依赖的对象,这些对象现在由IoC容器负责创建和管理。这样,对象之间的依赖关系被解耦,使得代码更加灵活和可重用。

依赖注入(Dependency Injection, DI)是实现IoC的一种技术,它允许对象通过容器动态地接收它们所依赖的其他对象的实例。这种方式允许开发者通过简单的配置而不是编写大量代码来指定依赖关系,从而提高了代码的可维护性和可重用性。

总结来说,IoC是一种设计原则,旨在减少代码之间的耦合,通过使用IoC容器和依赖注入技术,可以提高软件的可维护性、可重用性和灵活性。

5. Spring IoC 的实现机制是什么?

  1. 反射:Spring使用Java的反射机制来实现动态创建和管理Bean对象。通过反射,Spring可以在运行时动态地实例化Bean对象、调用Bean的方法和设置属性值。
  2. 配置元数据:Spring使用配置元数据来描述Bean的定义和依赖关系。配置元数据可以通过XML配置文件、注解和Java代码等方式进行定义。Spring在启动时会解析配置元数据,根据配置信息创建和管理Bean对象。
  3. Bean定义:Spring使用Bean定义来描述Bean的属性、依赖关系和生命周期等信息。Bean定义可以通过XML配置文件中的<bean>元素、注解和Java代码中的@Bean注解等方式进行定义。Bean定义包含了Bean的类名、作用域、构造函数参数、属性值等信息。
  4. Bean工厂:Spring的Bean工厂负责创建和管理Bean对象。Bean工厂可以是BeanFactory接口的实现,如DefaultListableBeanFactory。Bean工厂负责解析配置元数据,根据Bean定义创建Bean对象,并将其放入容器中进行管理。
  5. 依赖注入:Spring使用依赖注入来解决Bean之间的依赖关系。通过依赖注入,Spring容器负责将Bean所依赖的其他Bean实例注入到它们之中。Spring使用反射和配置元数据来确定依赖关系,并在运行时进行注入。

        总结起来,Spring的IoC底层实现机制主要依赖于反射、配置元数据、Bean定义、Bean工厂和依赖注入等技术和组件。通过这些机制,Spring实现了Bean的创建、配置和管理,以及Bean之间的解耦和依赖注入

6. Spring-Ioc容器的加载过程

spring 的 IOC 容器工作的过程,其实可以划分为两个阶段:配置解析阶段Bean 的创建段

1.  配置解析阶段

主要做的工作是加载和解析配置文件,将配置的bean解析成 BeanDefinition。整个过程是:

  1. 读取配置:通过BeanDefinitionReader读取配置文件或配置类
  2. 解析配置信息:如ComonentScan、Bean配置等
  3. 扫描类注解:根据ComonentScan扫描@Component、@Bean、@Configuration、@Import等注解...
  4. 将符合的bean注册为BeanDefinition

2.  Bean的创建过程

主要做的工作是根据 BeanDefinition创建Bean。

  1. 实例化Bean:容器根据配置文件中的Bean定义,实例化Bean对象。可以通过构造函数实例化、工厂方法实例化、静态工厂方法实例化等方式来创建Bean对象。
  2. 注入Bean属性:容器会为实例化的Bean对象设置属性值,可以通过setter方法注入属性值,也可以通过构造函数注入属性值。
  3. 处理依赖关系:容器会处理Bean之间的依赖关系,将依赖的Bean注入到需要的地方 。
  4. 执行初始化方法:容器会调用Bean的初始化方法,可以通过实现InitializingBean接口或在配置文件中指定初始化方法来定义Bean的初始化逻辑。
  5. 注册Bean:容器会将实例化、属性设置和初始化完成的Bean对象注册到容器中,以便后续的使用和管理。
  6. 完成加载:容器完成所有Bean的加载和初始化后,即完成了IoC容器的加载过程。此时,可以通过容器调用getBean获取Bean对象。

7. spring 自动装配 bean 有哪些方式

  1. 根据名称自动装配(byName):Spring容器会根据Bean的名称自动将相应的依赖注入到需要的地方。在XML配置中,可以使用autowire="byName"来启用byName自动装配。
  2. 根据类型自动装配(byType):Spring容器会根据Bean的类型自动将相应的依赖注入到需要的地方。在XML配置中,可以使用autowire="byType"来启用byType自动装配。
  3. 构造函数自动装配(constructor):Spring容器会根据构造函数的参数类型自动将相应的依赖注入到构造函数中。在XML配置中,可以使用autowire="constructor"来启用构造函数自动装配。
  4. 自动装配注解(Autowired):通过在需要自动装配的字段、构造函数或方法上使用@Autowired注解,Spring容器会自动将相应的依赖注入到标注了@Autowired的位置。

8. Spring-AOP通知和执行顺序? 

  1. 前置通知:在目标方法被调用之前调用通知功能;
  2. 后置通知:在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
  3. 返回通知:在目标方法成功执行之后调用通知;
  4. 异常通知:在目标方法抛出异常后调用通知;
  5. 环绕通知:通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

9. Spring AOP and AspectJ AOP 有什么区别?

两者的关系

  1. Spring Aop主要用到了AspectJ的@PointCut 切点解析能力和切点匹配能力。 @Aspect、@Before.等这些注解都是由AspectJ 发明的,
  2. AspectJ 能干很多 Spring AOP 干不了的事情,它是 AOP 编程的完全解决方案.Spring AOP 致力于解决的是企业级开发中最普遍的 AOP 需求

两者的区别

  1. AspectJ 主要通过在编译阶段生成代理类,也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的对象,通过这种方式实现AOP。
  2. SpringAOP并没有使用AspectJ的织入Java字节功能来增强对象。而是使用的动态代理来增强对象。默认地,如果使用接口的,用 JDK 提供的动态代理实现,如果没有接口,使用 CGLIB 实现Spring AOP 在容器启动的时候需要生成代理实例,在方法调用上也会增加栈的深度,使得 Spring AOP 的性能不如 AspectJ 那么好。

总结

Spring AOP 和 AspectJ AOP 都是优秀的 AOP 框架,但是它们的实现方式、性能和功能略有不同,开发者应根据自己的需求和实际情况来选择合适的框架。如果需要更加灵活、强大的 AOP 功能和更高的性能,可以选择 AspectJ AOP,如果只是简单的 AOP 功能,可以选择 Spring AOP。

 10. 说一下Spring的事务传播行为

务的传播特性指的是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行?通过@Transactional注解的propagation属性来指定事务传播行为

有多种类型:默认REQUIRED,也是适用于大多数情况

  1. REQUIRED:如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。这是最常用的传播行为,也是默认的,适用于大多数情况。
  2. REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务。如果当前存在事务,则将当前事务挂起。适用于需要独立事务执行的场景,不受外部事务的影响。
  3. SUPPORTS:如果当前存在事务,则加入该事务,如果当前没有事务,则以非事务方式执行。适用于不需要强制事务的场景,可以与其他事务方法共享事务。
  4. NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则将当前事务挂起。适用于不需要事务支持的场景,可以在方法执行期间暂时禁用事务。
  5. MANDATORY:如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常。适用于必须在事务中执行的场景,如果没有事务则会抛出异常。
  6. NESTED:如果当前存在事务,则在嵌套事务中执行,如果当前没有事务,则创建一个新的事务。嵌套事务是外部事务的一部分,可以独立提交或回滚。适用于需要在嵌套事务中执行的场景。
  7. NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。适用于不允许在事务中执行的场景,如果存在事务则会抛出异常。

11. 说一下 spring 的事务隔离级别?

Spring的事务隔离级别是指在并发环境下,事务之间相互隔离的程度。Spring框架支持多种事务隔离级别,可以根据具体的业务需求来选择适合的隔离级别。

通过@Transactional注解的isolation属性来指定事务隔离级别。

以下是常见的事务隔离级别:

  1. DEFAULT(默认):使用数据库默认的事务隔离级别。通常为数据库的默认隔离级别,如Oracle为READ COMMITTED,MySQL为REPEATABLE READ。
  2. READ_UNCOMMITTED:最低的隔离级别,允许读取未提交的数据。事务可以读取其他事务未提交的数据,可能会导致脏读、不可重复读和幻读的问题。
  3. READ_COMMITTED:保证一个事务只能读取到已提交的数据。事务读取的数据是其他事务已经提交的数据,避免了脏读的问题。但可能会出现不可重复读和幻读的问题。
  4. REPEATABLE_READ:保证一个事务在同一个查询中多次读取的数据是一致的。事务期间,其他事务对数据的修改不可见,避免了脏读和不可重复读的问题。但可能会出现幻读的问题。
  5. SERIALIZABLE:最高的隔离级别,保证事务串行执行,避免了脏读、不可重复读和幻读的问题。但会降低并发性能,因为事务需要串行执行。

需要根据具体的业务需求和并发情况来选择合适的事务隔离级别,以确保事务的隔离性和数据一致性。同时,需要注意不同数据库对事务隔离级别的支持可能有所差异

12. Bean有哪几种配置方式?

在Spring框架中,有以下几种常见的Bean配置方式:

  1. XML配置:使用XML文件来配置Bean,通过<bean>元素定义Bean的属性和依赖关系。可以使用Spring的XML命名空间和标签来简化配置。
  2. 注解配置:使用注解来配置Bean,通过在Bean类上添加注解,如@Component、@Service、@Repository等,来标识Bean的角色和作用。
  3. JavaConfig方式:使用Java类来配置Bean,通过编写一个配置类,使用@Configuration注解标识,然后在方法上使用@Bean注解来定义Bean。
  4. @Import:@Import注解可以用于导入其他配置类,也可以用于导入其他普通类。当导入的是配置类时,被导入的配置类中定义的Bean会被纳入到当前配置类的上下文中;当导入的是普通类时,被导入的类本身会被当作一个Bean进行注册。

13. BeanFactory 和ApplicationContext有什么区别?

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

BeanFactory:是Spring框架的核心接口之一, 我们可以称之为 “低级容器”。为什么叫低级容器呢?因为Bean的生产过程分为【配置的解析】和【Bean的创建】,而BeanFactory只有Bean的创建功能,但也说明它内存占用更小,在早期会在一些内存受限的可穿戴设备中作为spring容器使用。

ApplicationContext 可以称之为 “高级容器”。因为他比 BeanFactory 多了更多的功能。他继承了多个接口,因此具备了更多的功能。例如配置的读取、解析、扫描等,还加入了 如 事件事件监听机制,及后置处理器让Spring提升了扩展性。所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而是 “应用上下文”, 代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。

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

14. BeanFactory 和FactoryBean有什么区别?

BeanFactory是Spring框架的核心接口之一,用于管理和获取Bean对象亦陈为bean的容器。使用了简单工厂模式,提供getBean方法用来获取bean。

FactoryBean是一个bean,但是它是一个特殊的bean。它是一个接口,他必须被一个bean去实现。定义了两个方法:getObject()getObjectType()

getObjectType()方法用于返回创建的Bean对象的类型。

getObject()方法用于返回创建的Bean对象,

所以他们直接没有什么关系, 实在要扯上点关系那就是BeanFactory管理了FactoryBean,

15. Spring中bean的生命周期

Bean生命周期:指定的就是Bean从创建到销毁的整个过程: 分4大步:

实例化

  1. 推断构造方法,通过反射去推断构造函数进行实例化
  2. 实例工厂、 静态工厂

依赖注入(DI)

  1.  解析自动装配(byname bytype constractor none @Autowired),填充属性,也就是依赖注入

初始化

  1. 调用很多Aware回调方法
  2. 调用BeanPostProcessor.postProcessBeforeInitialization
  3. 调用生命周期回调初始化方法
  4. 初始化后,进行AOP,调用BeanPostProcessor.postProcessAfterInitialization, 如果bean实现aop则会在这里创建动态代理

销毁

  1. 在spring容器关闭的时候进行调用
  2. 调用生命周期回调销毁方法

16. 介绍下SpringAop的底层实现

Spring AOP是Spring框架的一个重要组成部分,用于实现面向切面编程。它通过在方法调用前、调用后或异常抛出时插入通知,允许开发者在核心业务逻辑之外执行横切关注点的代码。

底层实现主要分两部分:创建AOP动态代理调用代理

在启动Spring会创建AOP动态代理:

首先通过AspectJ解析切点表达式: 在创建代理对象时,Spring AOP使用AspectJ来解析切点表达式。它会根据定义的条件匹配目标Bean的方法。如果Bean不符合切点的条件,将跳过,否则将会通动态代理包装Bean对象:具体会根据目标对象是否实现接口来选择使用JDK动态代理或CGLIB代理。这使得AOP可以适用于各种类型的目标对象。

在调用阶段:

  1. Spring AOP使用责任链模式来管理通知的执行顺序。通知拦截链包括前置通知、后置通知、异常通知、最终通知和环绕通知,它们按照配置的顺序形成链式结构。
  2. 通知的有序执行: 责任链确保通知按照预期顺序执行。前置通知在目标方法执行前执行,后置通知在目标方法成功执行后执行,异常通知在方法抛出异常时执行,最终通知无论如何都会执行,而环绕通知包裹目标方法,允许在方法执行前后添加额外的行为。

综上所述,Spring AOP在创建启动阶段使用AspectJ解析切点表达式如果匹配使用动态代理,而在调用阶段使用责任链模式确保通知的有序执行。这些机制共同构成了Spring AOP的底层实现。

17. JDK动态代理和CGLIB动态代理的区别

从性能上特性对比:

JDK动态代理要求目标对象必须实现至少一个接口,因为它基于接口生成代理类。而CGLIB动态代理不依赖于目标对象是否实现接口,可以代理没有实现接口的类,它通过继承或者代理目标对象的父类来实现代理。

从创建代理时的性能对比:

JDK动态代理通常比CGLIB动态代理创建速度更快,因为它不需要生成字节码文件。而CGLIB动态代理的创建速度通常比较慢,因为它需要生成字节码文件。另外,JDK代理生成的代理类较小,占用较少的内存,而CGLIB生成的代理类通常较大,占用更多的内存。

从调用时的性能对比:

JDK动态代理在方法调用时需要通过反射机制来调用目标方法,因此性能略低于CGLIB,尽管JDK动态代理在Java 8中有了性能改进,但CGLIB动态代理仍然具有更高的方法调用性能。CGLIB动态代理在方法调用时不需要通过反射,直接调用目标方法,通常具有更高的方法调用性能,同时无需类型转换。

选择使用JDK动态代理还是CGLIB动态代理取决于具体需求。如果目标对象已经实现了接口,并且您更关注创建性能和内存占用,那么JDK动态代理可能是一个不错的选择。如果目标对象没有实现接口,或者您更关注方法调用性能,那么CGLIB动态代理可能更合适。综上所述,这两种代理方式各有优势,根据实际情况进行选择是明智的, Spring默认情况如果目标类实现了接口用JDK代理否则用CGLIB。 而SpringBoot默认用CGLIB,所以用哪个问题都不大。

18. Spring多线程事务 能否保证事务的一致性

在多线程环境下,Spring事务管理默认情况下无法保证全局事务的一致性。这是因为Spring的本地事务管理是基于线程的,每个线程都有自己的独立事务。

  1. Spring的事务管理通常将事务信息存储在ThreadLocal中,这意味着每个线程只能拥有一个事务。这确保了在单个线程内的数据库操作处于同一个事务中,保证了原子性。
  2. 可以通过如下方案进行解决:
    • 编程式事务: 为了在多线程环境中实现事务一致性,您可以使用编程式事务管理。这意味着您需要在代码中显式控制事务的边界和操作,确保在适当的时机提交或回滚事务。
    • 分布式事务: 如果您的应用程序需要跨多个资源(例如多个数据库)的全局事务一致性,那么您可能需要使用分布式事务管理(如2PC/3PC TCC等)来管理全局事务。这将确保所有参与的资源都处于相同的全局事务中,以保证一致性。

总之,在多线程环境中,Spring的本地事务管理需要额外的协调和管理才能实现事务一致性。这可以通过编程式事务、分布式事务管理器或二阶段提交等方式来实现,具体取决于您的应用程序需求和复杂性。

19. Spring事务的失效原因?

  1. 方法是private也会失效,解决:改成public: Spring的事务代理通常是通过Java动态代理或CGLIB动态代理生成的,这些代理要求目标方法是公开可访问的(public)。
  2. 目标类没有配置为Bean也会失效,解决:配置为Bean: Spring的事务管理需要在Spring容器中配置的Bean上才能生效。如果目标类没有被配置为Spring Bean,那么事务将无法被应用。解决方法是确保目标类被正确配置为Spring Bean。
  3. 自己捕获了异常,解决:不要捕获处理
  4. 使用CGLIB动态代理,但@Transactional声明在接口上: 默认情况下,Spring的事务代理使用基于接口的JDK动态代理。如果您将@Transactional注解声明在接口上,而目标类是使用CGLIB代理的,事务将不会生效。解决方法是将@Transactional注解移到目标类的方法上,或者配置Spring以使用CGLIB代理接口。
  5. 跨越多个线程的事务管理,解决:使用编程式事务或分布式事务: 如果您的应用程序在多个线程之间共享数据库连接和事务上下文,事务可能会失效,除非适当地配置事务传播属性。
  6. 事务传播属性或捕获异常等熟悉设置不正确: 事务传播属性定义了事务如何传播到嵌套方法或外部方法。如果事务传播属性设置不正确,可能会导致事务失效或不符合预期的行为。

20. Spring事件监听的核心机制是什么?

Spring事件监听的核心机制围绕观察者模式展开:

观察者模式: 它允许一个对象(称为主题或被观察者)维护一组依赖于它的对象(称为观察者),并在主题状态发生变化时通知观察者。

它包含三个核心:

  1. 事件: 事件是观察者模式中的主题状态变化的具体表示,它封装了事件发生时的信息。在Spring中,事件通常是普通的Java对象,用于传递数据或上下文信息。
  2. 事件发布者: 在Spring中,事件发布者充当主题的角色,负责触发并发布事件。它通常实现了ApplicationEventPublisher接口或使用注解@Autowired来获得事件发布功能。
  3. 事件监听器: 事件监听器充当观察者的角色,负责监听并响应事件的发生。它实现了ApplicationListener接口,通过onApplicationEvent()方法来处理事件。

总之,Spring事件监听机制的核心机制是观察者模式,通过事件、事件发布者和事件监听器的协作,实现了松耦合的组件通信,使得应用程序更加灵活和可维护。

21. Spring 框架中都用到了哪些设计模式?

简单工厂:

        BeanFactory:Spring的BeanFactory充当工厂,负责根据配置信息创建Bean实例。它是一种工厂模式的应用,根据指定的类名或ID创建Bean对象。

工厂方法

        FactoryBeanFactoryBean接口允许用户自定义Bean的创建逻辑,实现了工厂方法模式。开发人员可以使用FactoryBean来创建复杂的Bean实例。

单例模式

        Bean实例:Spring默认将Bean配置为单例,确保在容器中只有一个共享的实例,这有助于节省资源和提高性能。

适配器模式

        SpringMVC中的HandlerAdapter:SpringMVC的HandlerAdapter允许不同类型的处理器适配到处理器接口,以实现统一的处理器调用。这是适配器模式的应用。

装饰器模式    

​​​​​​​        BeanWrapper:Spring的BeanWrapper允许在不修改原始Bean类的情况下添加额外的功能,这是装饰器模式的实际应用。

代理模式

​​​​​​​​​​​​​​        AOP底层:Spring的AOP(面向切面编程)底层通过代理模式来实现切面功能,包括JDK动态代理和CGLIB代理。

观察者模式

​​​​​​​​​​​​​​        Spring的事件监听:Spring的事件监听机制是观察者模式的应用,它允许组件监听和响应特定类型的事件,实现了松耦合的组件通信。

策略模式

​​​​​​​​​​​​​​        excludeFilters、includeFilters:Spring允许使用策略模式来定义包扫描时的过滤策略,如在@ComponentScan注解中使用的excludeFiltersincludeFilters

模板方法模式

​​​​​​​​​​​​​​        Spring几乎所有的外接扩展:Spring框架的许多模块和外部扩展都采用模板方法模式,例如JdbcTemplate、HibernateTemplate等。

责任链模式

​​​​​​​​​​​​​​        AOP的方法调用:Spring AOP通过责任链模式实现通知(Advice)的调用,确保通知按顺序执行。

22. 单例Bean和单例模式

单例模式表示JVM中某个类的对象只会存在唯一一个。

而单例Bean并不表示JVM中只能存在唯一的某个类的Bean对象。

23. 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

24. 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等注解

相关推荐

  1. Spring-面试

    2024-04-25 11:04:06       62 阅读
  2. Spring面试

    2024-04-25 11:04:06       41 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-25 11:04:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-25 11:04:06       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-25 11:04:06       82 阅读
  4. Python语言-面向对象

    2024-04-25 11:04:06       91 阅读

热门阅读

  1. ❤网络跨域报错篇http

    2024-04-25 11:04:06       38 阅读
  2. Spring AOP 切面编程

    2024-04-25 11:04:06       37 阅读
  3. 时光流转:探秘STM32实时时钟RTC

    2024-04-25 11:04:06       33 阅读
  4. 【Linux】FTP安装部署及配置用户

    2024-04-25 11:04:06       37 阅读
  5. 数据安全风险评估流程

    2024-04-25 11:04:06       33 阅读
  6. 使用Spring Boot整合定时任务(Schedule)

    2024-04-25 11:04:06       38 阅读
  7. C#基础内容之枚举

    2024-04-25 11:04:06       30 阅读