Java 面试题【SpringBoot 篇】

说说 Springboot 的启动流程?

  1. 启动 main() 方法:应用从 main() 方法启动,并通过 SpringApplication.run() 引导应用启动。
  2. 创建SpringApplication:应用会创建SpringApplication 对象,推断应用类型、设置初始化器、设置启动监听器、确定主应用类。
  1. 准备环境:Spring Boot 在启动过程中准备应用环境,加载配置文件、系统环境变量以及命令行参数。
  2. 创建并刷新 ApplicationContext:创建应用上下文,加载配置类和自动配置类,注册 Bean 并执行依赖注入等初始化操作。
  3. 在刷新上下文时启动嵌入式 Web 服务器: 对于 Web 应用,Spring Boot 会自动启动嵌入式 Web 容器(默认 Tomcat),并注册相关的 Servlet 和 Filter。
  4. 发布应用已启动事件:对应监听 stated 事件逻辑会被触发。
  5. 执行 CommandLineRunner 和 ApplicationRunner: 在应用启动完成后,执行实现了 CommandLineRunnerApplicationRunner 接口的初始化逻辑。
  6. 发布 ready 事件、应用启动完成:触发 ApplicationReadyEvent,应用进入运行状态,处理业务请求或任务。

什么是 Spring Boot?

Spring Boot 是一个简化 Spring 应用程序开发的框架。它的主要目标是减少 Spring 应用程序的配置和开发复杂性,使我们能够更快地构建、测试和部署 Spring 应用

Spring Boot 主要特点

  1. 简化配置:Spring Boot 通过自动配置(@EnableAutoConfiguration),根据项目中的类路径依赖、环境变量等自动为应用配置适当的 Spring 模块,避免了大量的 XML 配置。
  2. 内置服务器:Spring Boot 内置了 Tomcat、Jetty、Undertow 等服务器,应用程序可以直接通过 java -jar 方式启动,而不需要部署到外部的 Web 服务器中。
  3. 快速开发:Spring Boot 提供了开箱即用的项目结构、默认配置和依赖管理,支持快速原型开发。它还提供了许多常用的开发工具(如开发时热部署、应用健康检查等)。
  4. 独立运行:Spring Boot 应用打包成一个独立的 JAR 或 WAR 包,可以通过命令行直接运行,简化了部署过程。

SpringBoot 的核心特性有哪些?

  1. 开箱即用,内嵌服务器。 spring boot 可以省略以前繁琐的 tomcat 配置,快速创建一个 web 容器。
  2. 自动化配置。 在 spring boot 中我们可以按照自动配置的规定(将自动加载的 bean 写在自己jar 包当中的 meta/info/spring.factories 文件中或者通过的注解 @Import 导入时加载指定的类)这样我们的配置类就会被 Springboot 自动加载到容器当中。 同时还支持通过改写yaml 和 propreties来覆盖默认配置
  3. 支持 jar 包运行。 传统部署web 容器都是打成 war 包放在 tomcat 中。spring boot 可以打成 jar 包只要有 java 运行环境即可运行 web 容器
  4. 完整的生态支持。 spring boot 可以随意整合 spring 全家桶的支持。像 Actuator 健康检查模块,Spring Data JPA 数据库模块,Spring Test 测试模块。这些都可以很优雅的集成在 springboot 当中。
  5. 监控、健康检查支持。 spring boot Actuator 支持开发者监控应用的运行状态,包括性能指标、应用信息和日志级别控制等。

SpringBoot 是如何实现自动配置的?

Spring Boot 的自动配置是通过 @EnableAutoConfiguration 注解实现,这个注解包含@Import({AutoConfigurationImportSelector.class})注解,导入的这个类会去扫描 classpath 下所有的 META-INF/spring.factories 中的文件,根据文件中指定的配置类加载相应的 Bean 的自动配置。

Spring Boot 支持哪些嵌入 Web 容器?

1)Tomcat(默认) :Tomcat 是一种轻量级、广泛使用的 Servlet 容器

2)JettyJetty 是一个高效的 Web 服务器和 Servlet 容器,通常用于嵌入式系统或对资源占用较敏感的环境。它比 Tomcat 更轻量,并且适合长连接应用(如 WebSocket、Comet)。

3)UndertowUndertow 是一个轻量级的高性能 Web 服务器和 Servlet 容器,适合用于处理高并发的 HTTP 请求。它支持异步 IO 和 HTTP/2,是一种灵活、性能出色的选择。

4)Netty(仅限 WebFlux):对于使用 Spring WebFlux 的响应式 Web 应用,Spring Boot 支持 Netty 作为嵌入式 Web 容器。Netty 是一个非阻塞的异步事件驱动框架,非常适合响应式编程模型和高并发应用。

Spring Boot 中 application.properties 和 application.yml 的区别是什么?

它们两者的区别就在于书写格式对配置而言效果是一样的,就是个人偏好问题。 默认优先级为:application.properties > application.yml

  • application.properties 使用键值对配置,键和值之间用等号或冒号分隔
  • application.yml 使用 YAML 格式,具有层级结构,使用缩进表示嵌套关系。适合复杂配置,阅读性更佳。
# application.properties
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=secret
# application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db
    username: root
    password: secret

如何在 Spring Boot 中定义和读取自定义配置?

my:
  custom:
    property: 1234

1)使用 @Value 注解:

@Value("${my.custom.property}")
private String myProperty;

2)使用 @ConfigurationProperties 注解:

@Component
@ConfigurationProperties(prefix = "my.custom")
public class MyCustomProperties {
    private String property;
}

3)使用 Environment 接口:

@Autowired
private Environment env;

public void someMethod() {
    String value = env.getProperty("my.custom.property");
}

Spring Boot 配置文件加载优先级你知道吗?

简单优先级:

  • 命令行参数 > JAR包外面的配置文件 > JAR包内的配置文件
  • 命令行参数 > application-{profile}.properties > application.properties > application.yml

Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?

  • SpringBoot 打包的 JAR 包可以直接部署运行(内嵌服务器,默认 Tomcat)
  • 普通的 JAR 包通常需要外部服务器或容器运行(例如:Tomcat)

SpringBoot 默认同时可以处理多少个请求?

SpringBoot 默认是 Tomcat 这个 web 容器,实际上是这取决于 tomcat 的线程池配置。

tomcat 的默认核心线程数是 10,最大线程数 200,队列长度无限。但是它的线程池机制和 JDK 默认线程池不一样,因为主要是 I/O 密集型的任务,所以 tomcat 改造了线程池策略,在核心线程数满了之后,会直接创建线程到最大线程数

所以,在默认的配置下,同一时刻,可以处理 200 个请求。 其他的请求只能排队了。

可以通过 server.tomcat.max-threads 修改最大最大工作线程数。

如何理解 Spring Boot 中的 starter?

在 Spring Boot 中,Starter 是一组有用的依赖集合,用于简化构建配置。Spring Boot 通过 Starter POMs 提供了各种常用功能模块的集成,开发者只需引入一个 Starter 依赖,便可以自动获得该模块的所有相关依赖和配置,而无需手动添加多个依赖库和配置文件。

有点像我们去买一些必需品,然后有人打包成一个套餐售卖,我们就不需要一个一个再去找了,直接一次性打包拿走,节省了时间。

在 Spring Boot 中你是怎么使用拦截器的?

拦截器可以用来进行权限校验、日志记录、处理异常等问题

1)创建拦截器类: 实现 HandlerInterceptor 接口,并实现接口中的方法,方法里面包括了几个请求时间点:请求前、请求后 、整个请求结束后(用于资源清理等操作)。

public class MyInterceptor implements HandlerInterceptor {

   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       System.out.println("请求开始前");
       return true;  // 返回 true 继续处理,false 则拦截请求
   }

   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("请求后");
   }

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception {
       System.out.println("请求完成");
   }
}

2)注册拦截器: 通过实现 WebMvcConfigurer 的 addInterceptors 方法来添加自定义的拦截器。

@Configuration
public class WebConfig implements WebMvcConfigurer {

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**");  // 拦截指定路径
   }
}

说说你对 Spring Boot 事件机制的了解?

Spring Boot 的事件机制,实际上是基于 Spring 的事件机制实现的,通过发布-订阅模式(使用观察者设计模式) ,主要用于应用程序中各个组件之间进行消息传递和解耦。

作用总结

  • 解耦:通过事件机制,可以在不同组件之间传递消息,而不需要它们之间有直接的依赖关系,从而提高了代码的可维护性和扩展性。
  • 异步处理:某些事件可以异步处理,从而提高应用程序的响应速度和性能。
  • 状态通知:通过事件机制,可以通知应用程序的不同部分发生了某些特定的状态变化,比如启动完成、环境准备就绪等。

步骤

  1. 创建事件类:定义一个事件类,继承自 ApplicationEvent,或者任何自定义对象(从 Spring 4.2 开始,事件不再局限于 ApplicationEvent,可以是任意对象)
  2. 发布事件:在需要的地方发布事件,使用 ApplicationEventPublisher
  3. 创建事件监听器:使用 @EventListener 注解创建事件监听器。
  4. 使用事件发布者:在应用程序中调用事件发布者的方法来发布事件

自定义事件例子

1)创建事件类

public class MyCustomEvent extends ApplicationEvent {

    private final String message;

    public MyCustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage(){
        return message;
    }

}

2)发布事件

@Service
public class MyEventPublisher {

   @Autowired
   private ApplicationEventPublisher eventPublisher;

   public void publishEvent(String message) {
       MyCustomEvent event = new MyCustomEvent(this, message);
       eventPublisher.publishEvent(event);
   }
}

3)监听事件

@Component
public class MyCustomListener {

    @EventListener
    public void handleCustomEvent(MyCustomEvent event) {
        System.out.println("监听到消息 - " + event.getMessage());
    }

}

4)测试

@SpringBootTest
class TestSpringBootApplicationTests {

    @Autowired
    private MyEventPublisher myEventPublisher;

    @Test
    void contextLoads() {
        myEventPublisher.publishEvent("哈喽!");
        myEventPublisher.publishEvent("你好!");
    }

}
监听到消息 - 哈喽!
监听到消息 - 你好!

Spring Boot 中如何实现异步处理?

主要有四种方式来实现异步处理:

  1. 使用 @Async 注解
  2. 使用 CompletableFuture(Java 8 引入的一个强大的异步编程工具)
  3. 使用 @Scheduled 注解
  4. 使用线程池
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容