Spring中的循环依赖

多个Bean之间互相引用,形成了一个循环的依赖关系。这种情况下,当Spring容器初始化这些Bean时,可能会出现问题,因为每个Bean在初始化时需要先创建依赖的Bean,而依赖的Bean又需要依赖其他的Bean,从而导致循环依赖问题。

Spring怎么解决循环依赖的

Spring会提前暴露还未初始化完成的Bean对象,这样在创建Bean时,即使有循环依赖,也可以通过提前暴露的引用来解决。这种方式适用于单例Bean,Spring也会为存在循环依赖的Bean创建一个代理对象,先创建一个代理对象作为依赖的引用,等到Bean初始化完成后,再将代理对象替换为实际的Bean,也可以使用构造器的方式进行注入,这样Bean在初始化时就可以得到它所依赖的Bean。

为什么要三级缓存?二级不行吗?

不行,他三级缓存是为了生成代理对象,如果是没有代理对象的情况他使用二级缓存是没有问题的。

@Autowired的实现原理

当Spring容器初始化时,会自动查找所有的Bean定义,然后尝试根据类的类型、名称等信息进行自动装配。在自动装配的过程中,Spring会查找与字段或方法参数类型匹配的Bean,然后将匹配的Bean注入到标注了@Autowired的地方。Spring会通过Bean的构造函数、Setter方法或直接字段注入来完成依赖注入。

怎么理解Spring中的AOP

他是一种面向切面编程的思想,能够实现横切关注点的模块化,提高代码的复用性和可维护性,同时把横切关注点集中管理,使代码更清晰和可维护。

你平时怎么使用AOP的

在一些日志的打印和性能监控方面

说说JDK动态代理和CGLIB动态代理

JDK动态代理适用于接口,CGLIB动态代理适用于无接口类,通过生成子类实现代理。选用取决于是否有接口,JDK更通用,CGLIB适合无接口情况。

Spring事务隔离级别

Spring框架支持以下五种事务隔离级别:

  1. DEFAULT(默认) :使用底层数据库默认的事务隔离级别。
  2. READ_UNCOMMITTED(读未提交) :允许一个事务读取另一个事务未提交的数据。可能导致脏读、幻读、不可重复读问题。
  3. READ_COMMITTED(读已提交) :保证一个事务只能读取到另一个事务已提交的数据,可以避免脏读问题。
  4. REPEATABLE_READ(可重复读) :保证一个事务在整个过程中可以多次读取同一数据,不会受其他事务的影响。可以避免脏读、不可重复读问题。
  5. SERIALIZABLE(串行化) :最高的隔离级别,确保所有事务按照顺序依次执行,避免所有并发问题。

Spring事务传播行为

Spring框架中定义了七种事务传播行为,用于控制方法在不同事务上下文中的行为。以下是这些事务传播行为:

  1. REQUIRED(默认) :如果当前存在事务,则加入该事务;如果没有事务,则创建一个新事务。是最常用的传播行为。
  2. SUPPORTS :如果当前存在事务,则加入该事务;如果没有事务,则以非事务方式执行。
  3. MANDATORY :要求当前必须存在事务,否则会抛出异常。
  4. REQUIRES_NEW :无论当前是否存在事务,都会创建一个新事务,并在方法执行完毕后提交。
  5. NOT_SUPPORTED :无论当前是否存在事务,都会以非事务方式执行。
  6. NEVER :要求当前不存在事务,如果存在则抛出异常。
  7. NESTED :如果当前存在事务,则在嵌套事务中执行;如果没有事务,则执行REQUIRED类似的操作。

声明式事务在哪些情况下会失效

  1. 当在同一个类的方法中调用另一个方法,而调用的方法带有声明式事务注解,事务可能会失效;
  2. 捕获了异常而不重新抛出,声明式事务可能无法正确处理异常,导致事务无法回滚;
  3. 非公开方法(private、protected等)上的声明式事务无法被代理,因为代理通常基于接口或类的public方法,在声明式事务中,如果使用编程式事务(如TransactionTemplate)来管理事务,可能会导致事务失效;
  4. 如果运行时异常被捕获并不再次抛出,事务可能无法正确回滚;
  5. 在多线程环境中,声明式事务可能无法正确传播,因为线程之间的事务隔离可能导致事务不生效。

Spring MVC的工作流程

  1. 客户端HTTP请求到Spring MVC应用的前端控制器DispatcherServlet
  2. DispatcherServlet是Spring MVC的核心控制器,它接收到所有的客户端请求,并将请求分发给不同的控制器。
  3. DispatcherServlet会查询Handler Mapping,它会根据请求的URL找到匹配的控制器(Handler)。
  4. 找到匹配的控制器后,DispatcherServlet会将请求交给对应的Controller进行处理。
  5. Controller处理请求后,会返回一个ModelAndView对象,其中包含了模型数据和视图名。
  6. View Resolver找到视图模板后,会将模型数据注入视图模板中,生成最终的HTML响应。
  7. 生成的HTML响应会由DispatcherServlet返回给客户端,完成请求-处理-响应的循环。

Spring boot自动配置原理

Spring Boot的自动配置是通过条件注解、自动配置类、spring.factories文件和配置属性等机制来实现的。条件注解判断何时应用自动配置,自动配置类提供预定义的Bean配置,spring.factories文件列出自动配置类,配置属性影响自动配置行为。

如何自定义一个起步依赖

自定义Spring Boot起步依赖的步骤如下:

  1. 创建项目 :使用Maven或Gradle创建一个新项目,作为你的自定义起步依赖项目。
  2. 定义自动配置类 :在项目中创建一个自动配置类(带有@Configuration注解),在其中定义需要自动配置的Bean和逻辑。
  3. 创建条件注解 :编写一个自定义的条件注解(带有@Conditional注解),用于决定何时应用你的自动配置。这个条件注解可以根据特定的条件来判断是否应用你的配置。
  4. 创建spring.factories文件 :在src/main/resources/META-INF目录下创建一个spring.factories文件,其中列出自动配置类和条件注解的全限定名。这个文件会被Spring Boot自动扫描,用于加载自定义的自动配置。
  5. 编写README文档 :创建一个清晰的README文档,描述你的起步依赖的用途、功能和使用方法,帮助其他开发者理解如何使用它。
  6. 发布到仓库 :将你的自定义起步依赖打包,并将其发布到Maven或其他仓库中,以便其他项目可以通过依赖管理工具引入它。

Spring Cloud中的核心组件及其应用

  1. Eureka :Eureka是一个服务注册和发现的组件
  2. Ribbon :Ribbon是一个负载均衡的客户端
  3. Feign :Feign是一个声明式的HTTP客户端
  4. Hystrix :Hystrix是一个断路器和容错的库
  5. Zuul :Zuul是一个网关服务
  6. Config :Config用于集中管理微服务的配置信息
  7. Bus :Bus用于在微服务之间传播状态变化和事件
  8. Stream :Stream是一个事件驱动的微服务通信框架
  9. Sleuth :Sleuth用于分布式系统中的请求追踪和跟踪
  10. nacos

Spring 中应用了哪些设计模式呢?

  1. 工厂模式 : Spring 容器本质是一个大工厂,使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
  2. 代理模式 : Spring AOP 功能功能就是通过代理模式来实现的,分为动态代理和静态代理。
  3. 单例模式 : Spring 中的 Bean 默认都是单例的,这样有利于容器对 Bean 的管理。
  4. 模板模式 : Spring 中 JdbcTemplate、RestTemplate 等以 Template 结尾的对数据库、网络等等进行操作的模板类,就使用到了模板模式。
  5. 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。ApplicationRunner
  6. 适配器模式 :Spring AOP 的增强或通知 (Advice) 使用到了适配器模式、Spring MVC 中也是用到了适配器模式适配 Controller。
  7. 策略模式:Spring 中有一个 Resource 接口,它的不同实现类,会根据不同的策略去访问资源。

说一说什么是 IOC? 什么是 DI?

IOC就是控制反转,将对象的创建、生命周期和对象的关系交给容器来管理,我们想要什么对象容器就给我们什么对象,DI的话就是当容器实例化一个对象的时候会把他的依赖对象注入给他

能说一下 Spring Bean 生命周期吗?

他分为四个阶段实例化(Instantiation)、属性赋值(Populate)、初始化(Initialization)、销毁(Destruction)

  1. 解析类得到BeanDefinition
  2. 如果有多个构造方法,则要推断构造方法
  3. 确定好构造方法后,进行实例化得到一个对象
  4. 对对象中的加了@Autowired注解的属性进行属性填充
  5. 回调Aware方法,比如BeanNameAware,BeanFactoryAware
  6. 调用BeanPostProcessor的初始化前的方法
  7. 调用初始化方法
  8. 调用BeanPostProcessor的初始化后的方法,在这里会进行AOP
  9. 如果当前创建的bean是单例的则会把bean放入单例池
  10. 使用bean
  11. Spring容器关闭时调用DisposableBean中destory(0方法

Spring 中的单例 Bean 会存在线程安全问题吗?

会存在,因为是单例的,所有线程都会使用这一个Bean,如果这个Bean是个无状态的,就是线程的操作对Bean中成员变量不会执行查询以外的操作他就是线程安全的。

最后修改:2023 年 08 月 27 日
如果觉得我的文章对你有用,请随意赞赏