文章
努力加载图片中...
Spring 面试题学习
  • 7330 字

  • 10 分钟

  • 10 次

  • 2025-10-13
标签:

说一下你对 Spring 的理解

我觉得 Spring 是 Java 后端开发中最核心的框架之一,它的核心思想是‘简化开发’

  • IoC容器:通过控制反转把对象的创建和依赖管理交给 Spring 容器来做。
  • AOP:面向切面编程,允许开发者定义横切关注点,它能帮我们把一些通用逻辑,比如日志、权限、事务这些,和业务代码解耦。比如加个 @Transactional 注解就能控制事务,代码更干净。
  • 一站式支持,除了核心容器,还有 Spring MVC 做 Web 层,Spring Boot 让项目快速启动,还有对数据访问、安全、消息等模块的整合,整个生态非常完整。

spring的核心思想说说你的理解?

我觉得 Spring 的核心思想就三点:IoC、DI 和 AOP

首先是 IoC(控制反转),简单说就是把对象的创建交给 Spring 容器来管理,我们不用自己 new 了,降低了代码之间的耦合。

然后是 DI(依赖注入),它是 IoC 的具体实现方式。比如一个 Service 依赖 Dao,Spring 会自动把 Dao 注入进去,代码更灵活,也更容易测试。

最后是 AOP(面向切面编程),用来处理像日志、事务、权限这些重复的逻辑。不用每个方法都写一遍,统一抽出来,通过代理机制在运行时织入,让业务代码更干净。

Spring IoC和AOP 介绍一下

IoC,叫控制反转,它的核心就是把对象的创建交给 Spring 容器来管理。以前我们都是 new Service() 来创建对象,耦合度高。用了 IoC 之后,Spring 帮我们创建和管理这些对象(也就是 Bean),需要用的时候直接注入就行。

AOP,是面向切面编程,主要是为了解决一些重复的、跟业务无关的逻辑,比如日志、事务、权限校验这些。AOP 就是把这些逻辑抽出来,通过“动态代理”在不修改原代码的情况下,统一加到指定的方法上。

Spring的aop介绍一下

好的,我理解的 AOP,就是面向切面编程,它的主要作用是把一些重复的、跟业务无关的逻辑,比如日志、事务、权限这些,统一抽出来管理

它通过动态代理,在不改原有代码的情况下,把这些通用逻辑‘编织’到指定的方法前后。 Spring AOP 主要用两种代理方式:

  • 如果目标对象有接口,就用 JDK 动态代理
  • 没有接口的话,就用 CGLIB 生成子类代理

简单说:AOP 让业务代码更干净,通用逻辑更集中,维护起来也更方便。

IOC和AOP是通过什么机制来实现的?

IoC 的实现主要靠三个东西:工厂模式、反射、和依赖注入。

Spring 把所有对象都放在一个容器里管理,这个容器就像一个工厂,负责创建和管理这些对象(也就是 Bean)。它通过 Java 的反射机制,在程序运行时动态地创建对象、调用方法、设置属性,不用你手动 new。

然后通过 依赖注入(DI),比如 @Autowired,容器会自动把需要的对象“塞”进去,实现解耦。


AOP 呢,主要是靠动态代理来实现的。

Spring 在运行时会生成一个代理对象,来“增强”原来的方法。它有两种方式:

  • 如果目标对象有接口,就用 JDK 动态代理
  • 如果没接口,就用 CGLIB 动态生成一个子类来做代理。

怎么理解SpringIoc?

IoC 叫控制反转,核心就是把对象的控制权交给 Spring 容器

以前我们写代码,要哪个对象就直接 new 一个,对象之间的依赖特别紧,耦合度高。现在不用了,我们只需要告诉 Spring:‘我需要什么对象’,它就会自动创建、装配好,再给我们用。

这个‘反转’体现在哪儿呢?
原来是我们主动 new 对象,现在是Spring 帮我们创建和管理——从“主动创建”变成“被动接收”,控制权从程序交给了容器。

这样一来,对象的创建、依赖注入、甚至销毁,都由 Spring 统一管理,代码更松耦合,也更容易维护和测试。

依赖倒置,依赖注入,控制反转分别是什么?

依赖倒置(DIP) 是一个设计原则,说的是:
高层模块(比如业务逻辑)不要去依赖底层模块(比如数据库实现),它们都应该依赖同一个抽象(比如接口)。
比如订单服务不要直接依赖 MySQL,而是依赖一个 OrderRepository 接口,这样换数据库就不影响业务。

控制反转(IoC) 是一种设计思想,是依赖倒置的实现方式之一。
它把对象的创建和流程控制权从代码里“反转”给容器(比如 Spring)来管理,不再由我们手动 new。

依赖注入(DI) 是 IoC 的具体实现手段,就是把依赖的对象“注入”进去。
比如通过构造函数、@Autowired 注入一个 Service,而不是在类里面自己 new。

依赖注入了解吗?怎么实现依赖注入的?

依赖注入(DI) 就是把对象之间的依赖关系交给 Spring 容器来管理,而不是在类里面自己 new。 比如一个 Service 要用 Dao,以前我们直接 new UserDao(),耦合太紧。现在只要声明‘我需要这个依赖’,Spring 会在运行时自动把对象‘塞’进来,解耦了,也更容易测试和替换实现。

在 Spring 中,常见的注入方式有三种:

  1. 构造器注入:通过构造函数传入依赖,证对象初始化时依赖已就绪。
  2. Setter 注入:通过 set 方法设置依赖,灵活性高,但可能依赖没初始化完。
  3. 字段注入:直接在字段上加 @Autowired,代码简洁但隐藏依赖关系。

动态代理是什么?

动态代理,简单说就是在程序运行时,自动生成一个代理对象,用来‘增强’原来的功能,而且不用改原始类的代码。 比如我想在某个方法执行前后加日志,又不想动它的源码,就可以用动态代理。

Java 里主要有两种:

  1. JDK 动态代理:要求目标对象必须实现了接口。Spring 会生成一个实现同样接口的代理对象,通过 InvocationHandler 拦截方法调用,并通过 invoke() 方法把逻辑转发过去。
  2. CGLIB 代理:如果目标对象没实现接口,JDK 就搞不定了。这时候 Spring 会用 CGLIB,动态生成一个它的子类,然后重写方法来实现拦截。

动态代理和静态代理的区别

静态代理是程序员提前写好的,比如给某个类写一个代理类,编译的时候就固定了。它只能代理一个具体的类,如果要代理多个类,就得写很多的代理类,太麻烦,不灵活。

动态代理是在程序运行时通过反射机制动态生成的,不需要提前写好。它可以代理一个接口下的多个实现类,只要规则定好了,一个代理逻辑就能套在多个对象上。

AOP实现有哪些注解?

  • @Aspect:用于定义切面,标注在切面类上。
  • @Pointcut:定义切点,标注在方法上,用于指定连接点。
  • @Before:在方法执行之前执行通知。
  • @After:在方法执行之后执行通知。
  • @Around:在方法执行前后都执行通知。
  • @AfterReturning:在方法执行后返回结果后执行通知。
  • @AfterThrowing:在方法抛出异常后执行通知。
  • @Advice:通用的通知类型,可以替代@Before、@After等。

什么是反射?有哪些使用场景?

反射机制是允许程序能够在运行状态下获取类的属性和方法并动态操作对象,获取属性和调用方法的一种机制。

它最常用的场景就是在框架里,比如 Spring:

  • IoC 容器就是靠反射来创建 Bean 的。你加个 @Service,Spring 启动时扫描到,就用反射把这个类实例化,不用你手动 new。
  • 依赖注入也是,@Autowired 一加,Spring 就用反射找到对应的对象,自动塞进去。
  • 还有 AOP 动态代理,调用原有方法也是反射实现的。

spring是如何解决循环依赖的?

Spring 主要是通过 三级缓存 + 提前暴露对象 的机制,来解决单例模式下 setter 注入的循环依赖问题。

  • 一级缓存:放的是完全创建好的 Bean。
  • 二级缓存:放的是提前暴露的半成品对象(可能还是原始对象,也可能是代理对象),专门用来解决循环依赖。
  • 三级缓存:放的是一个工厂(ObjectFactory),这个工厂能生成那个半成品对象

A 依赖 B,B 又依赖 A。

Spring 先创建 A,调完构造函数后,A 还没初始化完,是个‘半成品’。这时候 Spring 就把一个能生成 A 的工厂放进三级缓存

然后继续给 A 注入属性,但发现 A 依赖 B,且 B 还没创建,就开始创建 B。Spring 就去三级缓存里找工厂,调用它生成 A 的早期引用(如果 A 需要 AOP,这里还能提前生成代理),把这个引用放到二级缓存,再注入给 B。

B 创建完,回过头来继续完成 A 的属性注入,用的其实就是二级缓存里那个提前暴露的引用。

这样,A 和 B 就都能顺利创建了。

但要注意:案仅适用于 Setter/Field 注入的单例Bean;构造器注入因必须在实例化前获得依赖,仍会导致循环依赖。

Spring为什么用3级缓存解决循环依赖问题?用2级缓存不行吗?

Spring 用三级缓存,主要是为了正确处理 AOP 代理的情况。

举个例子:A 依赖 B,B 又依赖 A,而且 A 加了 @Transactional,需要生成代理对象。

如果只有二级缓存,Spring 创建 A 时,只能先把 A 的原始对象提前放进去。B 创建时就会拿到这个原始对象注入进去。

但 A 后续初始化时,Spring 又会生成一个代理对象,放进一级缓存。

结果就是:B 里面用的是原始对象,容器里存的是代理对象——同一个 Bean 出了两个版本,破坏了单例,事务也失效了。

而三级缓存的巧妙之处在于,它存的不是一个对象,而是一个工厂(ObjectFactory)

当 B 需要 A 时,Spring 调用这个工厂的 getObject(),这时 Spring 就能判断:A 需要代理吗?需要,那就提前生成代理对象,放进二级缓存,再注入给 B。

这样,B 拿到的就是最终形态的代理对象,后面 A 初始化完也不会再变,保证了全局唯一、形态一致

所以,三级缓存的本质是:延迟决策,按需生成正确的对象,二级缓存做不到这一点。

spring框架中都用到了哪些设计模式

  • 工厂设计模式
  • 代理设计模式
  • 单例设计模式
  • 模板方法模式
  • 包装器设计模式
  • 观察者模式
  • 适配器模式

spring 常用注解有什么?

Spring 常用的注解我大概分几类来说:

第一类:声明 Bean 的

  • @Component:通用注解,标记一个类交给 Spring 管理。
  • @Service:专门用在服务层,比如业务逻辑类。
  • @Repository:用在数据层,比如 DAO 或 Mapper,还能把数据库异常统一转换。
  • @Controller:用在控制层,配合 MVC 处理请求。
    其实后三个都是 @Component 的特殊版,只是语义更明确。

第二类:注入依赖的

  • @Autowired:自动装配,最常用,Spring 会按类型把 Bean “塞”进来,配合 @Qualifier 可以指定名字。

第三类:配置相关的

  • @Configuration:标记一个类是配置类,相当于以前的 XML 配置。
  • @Bean:写在方法上,把方法返回的对象注册成 Bean,比如配置数据源、Redis 客户端这些。

现在开发中还常用 @RestController,它是 @Controller + @ResponseBody 的组合,直接返回 JSON 数据,写接口特别方便。

Spring的事务什么情况下会失效?

  1. 未捕获异常: 如果一个事务方法中发生了未捕获的异常,并且异常未被处理或传播到事务边界之外,那么事务会失效,所有的数据库操作会回滚。
  2. 非受检异常: 默认情况下,Spring对非受检异常(RuntimeException或其子类)进行回滚处理,这意味着当事务方法中抛出这些异常时,事务会回滚。
  3. 事务传播属性设置不当: 如果在多个事务之间存在事务嵌套,且事务传播属性配置不正确,可能导致事务失效。特别是在方法内部调用有 @Transactional 注解的方法时要特别注意。
  4. 多数据源的事务管理: 如果在使用多数据源时,事务管理没有正确配置或者存在多个 @Transactional 注解时,可能会导致事务失效。
  5. 跨方法调用事务问题: 如果一个事务方法内部调用另一个方法,而这个被调用的方法没有 @Transactional 注解,这种情况下外层事务可能会失效。
  6. 事务在非公开方法中失效: 如果 @Transactional 注解标注在私有方法上或者非 public 方法上,事务也会失效。

Spring 事务失效最常见的有这么几种情况:

  1. 异常被自己 try-catch 了,但没再抛出来
    比如方法加了 @Transactional,里面发生异常你用 try-catch 捕获了,但没重新抛,Spring 就认为“没出错”,就不会回滚。

  2. 方法不是 public 的
    @Transactional 只对 public 方法有效。如果你把它加在 private 或 protected 方法上,事务直接不生效,这是底层代理的限制。

  3. 自己类里调用自己(自调用问题)
    比如 A 方法加了事务,它内部调用本类的 B 方法(B 也有事务),因为没走代理对象,事务就失效了。

  4. 异常类型不对
    默认只对 RuntimeExceptionError 回滚。如果你抛的是 Exception 这种检查异常,事务不会回滚,除非你手动配置 @Transactional(rollbackFor = Exception.class)

  5. 多数据源没配好事务管理器
    比如用了两个数据库,但事务管理器没指定清楚,可能会导致事务控制不住,这种情况在分布式场景下特别要注意。

Spring的事务,使用this调用是否生效?

不能生效。

因为Spring事务是通过代理对象来控制的,只有通过代理对象的方法调用才会应用事务管理的相关规则。当使用this直接调用时,是绕过了Spring的代理机制,因此不会应用事务设置。

Bean的生命周期说一下?

  1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
  2. Bean实例化后对将Bean的引入和值注入到Bean的属性中。
  3. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法。
  4. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入。
  5. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
  6. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
  7. 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
  8. 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
  9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
  10. 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

Bean 的生命周期我理解主要分四个阶段:实例化 → 属性填充 → 初始化 → 销毁

  1. 实例化:Spring 通过反射,调用构造函数,把 Bean 的对象 new 出来,这时候对象有了,但属性还是空的。

  2. 属性填充:把 @Autowired 注入的依赖、@Value 配置的值,都设置进去。

  3. 初始化(这是最复杂的一步):

    • 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入 Bean 的名字。
    • 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
    • 如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanFactory()方法,传入 BeanFactory对象的实例。
    • 与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。
    • 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行 BeanPostProcessor 的 前置处理postProcessBeforeInitialization)。
    • 接着执行初始化方法:先看有没有实现 InitializingBean 的 afterPropertiesSet(),再看有没有配置 init-method 或 @PostConstruct
    • 最后再触发 BeanPostProcessor 的 后置处理postProcessAfterInitialization),AOP 代理就是在这里生成的。
  4. 销毁

    • 当容器关闭时,会调用销毁方法:先执行 @PreDestroy 或 destroy-method,再执行 DisposableBean 的 destroy() 方法。

Bean是否单例?

Spring 中的 Bean 默认都是单例的。

Bean的单例和非单例,生命周期是否一样

不一样的,Spring Bean 的生命周期完全由 IoC 容器控制。Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 Bean,Spring 在创建好交给使用者之后,则不会再管理后续的生命周期。

Spring bean的作用域有哪些?

Spring 的 Bean 作用域主要有五种,最常用的是前两个:

  1. Singleton(单例)默认作用域。整个应用只创建一个实例,所有地方用的都是同一个对象。
  2. Prototype(原型):每次 getBean 都会创建一个新实例,Spring 创建完就不管了,销毁也得自己负责。

另外三个是 Web 环境下的: 3. Request:每个 HTTP 请求创建一个实例,请求结束就销毁。适合保存请求级别的数据。 4. Session:每个用户会话一个实例,用户退出就销毁。比如存登录用户信息。 5. Application:当前 ServletContext 中只存在一个 Bean 实例,用于应用程序范围内共享的 Bean。

Spring容器里存的是什么?

在Spring容器中,存储的主要是Bean对象

Bean是Spring框架中的基本组件,用于表示应用程序中的各种对象。当应用程序启动时,Spring容器会根据配置文件或注解的方式创建和管理这些Bean对象。Spring容器会负责创建、初始化、注入依赖以及销毁Bean对象。

在Spring中,在bean加载/销毁前后,如果想实现某些逻辑,可以怎么做

想在 Bean 创建后或销毁前加点逻辑,Spring 提供了好几种方式,我主要说常用的:

  1. 最推荐的是用注解

    • @PostConstruct:标记的方法会在 Bean 初始化完成后自动执行,比如用来加载缓存、初始化连接。
    • @PreDestroy:标记的方法会在 Bean 销毁前执行,比如用来关闭资源、释放连接。 这两个是标准注解,不依赖 Spring 接口,最常用。
  2. 也可以实现 Spring 的接口

    • 实现 InitializingBean,重写 afterPropertiesSet(),效果类似 @PostConstruct
    • 实现 DisposableBean,重写 destroy(),效果类似 @PreDestroy。 但这种方式会和 Spring 耦合,现在用得少了。
  3. XML 或 Java 配置里指定方法: 比如用 @Bean(initMethod = "init", destroyMethod = "close"),指定初始化和销毁方法,适合第三方类没法加注解的情况。

MVC分层介绍一下?

MVC 就是一种分层设计模式,把代码分成三块,各干各的活:

  • Model(模型):代表一个存取数据的对象或 JAVA POJO(Plain Old Java Object,简单java对象)。模型分为两类,一类称为数据承载 Bean,也就是实体类,承载业务数据的;一类称为业务处理Bean,也就是 Service 或 Dao 对象, 专门用于处理用户提交请求的。
  • View(视图):为用户提供使用界面,与用户直接进行交互。
  • Controller(控制器):用于将用户请求转发给相应的 Model 进行处理,并根据 Model 的计算结果向用户提供相应响应。实现视图与模型分离。

流程是这样的: 用户点页面 → 请求发给 Controller → Controller 找 Model 处理数据 → Model 把结果返回 → Controller 再找一个 View 页面,把数据显示出来,返回给用户。

了解SpringMVC的处理流程吗?

  1. 用户发送请求至前端控制器 DispatcherServlet 。
  2. DispatcherServlet 收到请求调用处理器映射器 HandlerMapping 根据请求 url 找到具体的处理器,生成处理器执行链 HandlerExecutionChain (包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。
  3. DispatcherServlet 根据处理器 Handler 获取处理器适配器 HandlerAdapter 执行HandlerAdapter 处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作
  4. 执行处理器 Handler(Controller,也叫页面控制器)。执行完成返回 ModelAndView,HandlerAdapter 将 ModelAndView 返回到 DispatcherServlet。
  5. DispatcherServlet 将ModelAndView 传给 ViewReslover 视图解析器,解析后返回具体 View。
  6. DispatcherServlet 对 View 进行渲染视图,也就是将模型数据 model 填充至视图中,然后响应给用户。

Handlermapping 和 handleradapter有了解吗?

HandlerMapping:

  • 作用:HandlerMapping负责将请求映射到处理器(Controller)。

HandlerAdapter:

  • 作用:根据处理器的接口类型,选择相应的HandlerAdapter来调用处理器。

为什么使用springboot (SpringBoot比Spring好在哪里)

  • 简化开发:Spring Boot通过提供一系列的开箱即用的组件,简化了项目的配置,不需要花费过多时间在繁琐的配置上。
  • 快速启动:Spring Boot提供了快速的应用程序启动方式,可通过内嵌的Tomcat等容器快速启动应用程序。
  • 自动化配置:Spring Boot通过自动配置功能,根据项目中的依赖关系和约定俗成的规则来配置应用程序,减少了配置的复杂性。

SpringBoot用到哪些设计模式?

  • 工程方法模式
  • 简单工厂模式
  • 代理模式
  • 单例模式
  • 模板模式
  • 装饰品模式
  • 观察者模式
  • 适配器模式
  • 策略模式

怎么理解SpringBoot中的约定大于配置

约定大于配置’简单说就是:Spring Boot 给我们定了一套‘默认规矩’,只要跟着它的套路走,就不用写一堆配置,开发特别快。

主要体现在三方面:

  1. 自动配置:比如你加了 spring-boot-starter-web,它就自动把 Tomcat 和 Spring MVC 都配好了,不用你写一行 XML 或配置类,有依赖就自动生效

  2. 默认配置:像日志、数据库连接、端口这些,它都给了合理的默认值。比如日志默认就输出到控制台,不用你去配 log4j 的路径和级别,不用改就能用

  3. 项目结构有约定:它建议我们把启动类放根包,Controller 放 controller 包,Service 放 service 包。大家按这个来,代码结构统一,新人一看就懂,协作效率高。

SpringBoot自动装配原理是什么?

它的核心是 @EnableAutoConfiguration 注解,而这个注解背后最关键的是一个叫 AutoConfigurationImportSelector 的类。

整个过程分三步:

  1. 扫描:项目一启动,它就会去所有 jar 包里找 META-INF/spring.factories 这个文件,将文件中配置的类型信息加载到 Spring 容器。
  2. 筛选:过滤出实现了 AutoConfiguration 接口的自动配置类,使用条件判断机制,过滤掉不满足条件的自动配置类。
  3. 导入:把符合条件的自动配置类导入 Spring 容器。

说几个启动器(starter)?

  • spring-boot-starter-web:这是最常用的起步依赖之一,它包含了Spring MVC和Tomcat嵌入式服务器,用于快速构建Web应用程序。
  • mybatis-spring-boot-starter:这个Starter是由MyBatis团队提供的,用于简化在Spring Boot应用中集成MyBatis的过程。
  • spring-boot-starter-data-redis:用于集成Redis缓存和数据存储服务。
  • spring-boot-starter-test:包含了单元测试和集成测试所需的库。
  • spring-boot-starter-jdbc:配置数据库连接,实现与数据库交互。
  • spring-boot-starter-security:提供了Spring Security的基本配置,帮助开发者快速实现应用的安全性,包括认证和授权功能。

SpringBoot里面有哪些重要的注解?还有一个配置相关的注解是哪个?

Spring Boot 中一些常用的注解包括:

  1. 应用
    • @SpringBootApplication:用于标注主应用程序类,标识一个Spring Boot应用程序的入口点,同时启用自动配置和组件扫描。
    • @Component:通用的Spring组件注解,表示一个受Spring管理的组件。
    • @Configuration:用于指定一个类为配置类,其中定义的bean会被Spring容器管理。通常与@Bean配合使用,@Bean用于声明一个Bean实例,由Spring容器进行管理。
  2. 组件
    • @Controller:标识控制器类,处理HTTP请求。
    • @RestController:结合@Controller和@ResponseBody,返回RESTful风格的数据。
    • @Service:标识服务类,通常用于标记业务逻辑层。
    • @Repository:标识数据访问组件,通常用于标记数据访问层。
  3. 方法
    • @Autowired:用于自动装配Spring Bean。
    • @Value:用于注入配置属性值。
    • @RequestMapping:用于映射HTTP请求路径到Controller的处理方法。
    • @GetMapping、@PostMapping、@PutMapping、@DeleteMapping:简化@RequestMapping的GET、POST、PUT和DELETE请求。

另外,一个与配置相关的重要注解是:

  • @Configuration:用于指定一个类为配置类,其中定义的bean会被Spring容器管理。通常与@Bean配合使用,@Bean用于声明一个Bean实例,由Spring容器进行管理。

springboot怎么开启事务?

在服务层的方法上添加 @Transactional 注解即可。

Springboot怎么做到导入就可以直接使用的?

Spring Boot 能做到‘一引依赖就可用’,主要靠三样东西配合:起步依赖(Starter)、自动配置、条件注解

  1. 起步依赖(Starter):比如 spring-boot-starter-web,它不是功能代码,而是一个‘依赖打包包’。你加了它,Spring Boot 就自动把 Web 开发需要的 Spring MVC、Tomcat、JSON 等一堆依赖全给你引入了,不用一个个写。

  2. 自动配置:项目一启动,Spring Boot 就会去每个 jar 包里找 META-INF/spring.factories 文件,这里面列了一堆‘可以自动配置的类’,比如 WebMvcAutoConfiguration

  3. 条件注解控制生效:这些配置类不是无脑加载的,而是用 @ConditionalOnClass@ConditionalOnMissingBean 这些注解控制的。

SpringBoot 过滤器和拦截器说一下?

  1. 过滤器(Filter)
    • 是 Servlet 规范的东西,不依赖 Spring。
    • 作用范围更广:所有请求都拦,包括静态资源(比如 .css、.js)。
    • 执行时机早,当请求进入 Servlet 容器时,会按照配置的顺序依次经过各个过滤器,然后再到达目标 Servlet 或控制器;响应返回时,也会按照相反的顺序再次经过这些过滤器。。
    • 缺点是不能直接注入 Spring 的 Bean,要用工具类间接获取。
  2. 拦截器(Interceptor)
    • 是 Spring MVC 自己的机制,属于 Spring 框架。
    • 只拦截 Controller 层的请求,静态资源不走它。
    • 执行在 DispatcherServlet 之后,当请求到达控制器时,会先经过拦截器的 preHandle 方法,如果该方法返回 true,则继续执行后续的控制器方法和其他拦截器;在控制器方法执行完成后,会调用拦截器的 postHandle 方法;最后,在请求处理完成后,会调用拦截器的 afterCompletion 方法
    • 支持直接 @Autowired 注入 Bean。

来源: Spring面试题 | 小林coding | Java面试学习

作者: Xigrut发布时间: 2025-10-13 11:52:39上次编辑时间: 2026-06-18 19:23:29 许可协议: CC BY-NC-SA 4.0
留言区