🎓博主介绍:Java、Python、js全栈开发 “多面手”,精通多种编程语言和技术,痴迷于人工智能领域。秉持着对技术的热爱与执着,持续探索创新,愿在此分享交流和学习,与大家共进步。
📖全栈开发环境搭建运行攻略:多语言一站式指南(环境搭建+运行+调试+发布+保姆级详解)
👉感兴趣的可以先收藏起来,希望帮助更多的人
10 个高频 Spring Boot 面试题解析:从自动装配到热部署原理
一、Spring Boot 自动装配原理
1.1 什么是自动装配
Spring Boot 的自动装配是指 Spring Boot 根据项目中添加的依赖,自动配置 Spring 应用程序的功能。例如,当我们在项目中添加了 Spring Data JPA 的依赖,Spring Boot 会自动配置数据源、JPA 实体管理器等。
1.2 自动装配的实现机制
Spring Boot 的自动装配主要通过 @EnableAutoConfiguration
注解实现。该注解会触发 Spring Boot 的自动配置机制,它会扫描 META-INF/spring.factories
文件,该文件中定义了一系列的自动配置类。
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@SpringBootApplication
注解包含了 @EnableAutoConfiguration
注解,因此在启动 Spring Boot 应用时,会自动进行自动装配。
1.3 自动装配的条件注解
Spring Boot 还提供了一系列的条件注解,如 @ConditionalOnClass
、@ConditionalOnMissingBean
等,用于控制自动配置类的加载。例如:
@Configuration
@ConditionalOnClass(JdbcTemplate.class)
public class JdbcAutoConfiguration {
// 配置 JdbcTemplate 的相关 Bean
}
上述代码表示只有当 JdbcTemplate
类存在于类路径中时,才会加载 JdbcAutoConfiguration
配置类。
二、Spring Boot Starter 原理
2.1 什么是 Starter
Spring Boot Starter 是一种依赖集合,它将相关的依赖打包在一起,方便开发者使用。例如,spring-boot-starter-web
包含了 Spring MVC、Tomcat 等相关依赖,开发者只需要添加该 Starter 依赖,就可以快速搭建一个 Web 应用。
2.2 Starter 的实现原理
Starter 本质上是一个 Maven 或 Gradle 依赖,它通过 pom.xml
或 build.gradle
文件来管理依赖。例如,spring-boot-starter-web
的 pom.xml
文件中包含了以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
</dependencies>
通过这种方式,开发者只需要添加一个 Starter 依赖,就可以引入多个相关依赖。
三、Spring Boot 的配置文件加载顺序
3.1 配置文件类型
Spring Boot 支持多种配置文件类型,如 application.properties
、application.yml
等。
3.2 配置文件加载顺序
Spring Boot 会按照以下顺序加载配置文件:
- 命令行参数
SPRING_APPLICATION_JSON
中的属性ServletConfig
初始化参数ServletContext
初始化参数- JNDI 属性(
java:comp/env
) - Java 系统属性(
System.getProperties()
) - 操作系统环境变量
RandomValuePropertySource
提供的随机属性- 打包在 jar 外部的
application-{profile}.properties
或application-{profile}.yml
文件 - 打包在 jar 内部的
application-{profile}.properties
或application-{profile}.yml
文件 - 打包在 jar 外部的
application.properties
或application.yml
文件 - 打包在 jar 内部的
application.properties
或application.yml
文件 @Configuration
类上的@PropertySource
注解指定的属性源- 默认属性(通过
SpringApplication.setDefaultProperties
指定)
3.3 示例代码
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.setDefaultProperties(Collections.singletonMap("server.port", "8081"));
app.run(args);
}
}
上述代码通过 setDefaultProperties
方法设置了默认属性。
四、Spring Boot 如何实现日志管理
4.1 默认日志框架
Spring Boot 默认使用 Logback 作为日志框架。当我们创建一个 Spring Boot 项目时,会自动引入 Logback 的依赖。
4.2 配置日志
我们可以通过 application.properties
或 application.yml
文件来配置日志。例如,在 application.properties
中配置日志级别:
logging.level.root=INFO
logging.level.com.example=DEBUG
上述代码将根日志级别设置为 INFO
,将 com.example
包下的日志级别设置为 DEBUG
。
4.3 自定义日志配置文件
我们也可以自定义 Logback 的配置文件,只需要在 src/main/resources
目录下创建 logback.xml
文件。例如:
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
五、Spring Boot 如何集成 MyBatis
5.1 添加依赖
在 pom.xml
中添加 MyBatis 和 MyBatis Spring Boot Starter 的依赖:
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
5.2 配置数据源
在 application.properties
中配置数据源信息:
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
5.3 创建实体类和 Mapper 接口
创建实体类:
public class User {
private Long id;
private String name;
// 省略 getter 和 setter 方法
}
创建 Mapper 接口:
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
List<User> findAll();
}
5.4 创建 Mapper XML 文件
在 src/main/resources
目录下创建 mapper
目录,并在该目录下创建 UserMapper.xml
文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="findAll" resultType="com.example.entity.User">
SELECT * FROM user
</select>
</mapper>
5.5 使用 Mapper 接口
在 Service 层中使用 Mapper 接口:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> findAllUsers() {
return userMapper.findAll();
}
}
六、Spring Boot 如何实现异步方法调用
6.1 启用异步支持
在 Spring Boot 主类上添加 @EnableAsync
注解:
@SpringBootApplication
@EnableAsync
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
6.2 创建异步方法
在需要异步执行的方法上添加 @Async
注解:
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
@Async
public void asyncMethod() {
try {
Thread.sleep(5000);
System.out.println("异步方法执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
6.3 调用异步方法
在其他类中调用异步方法:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CallerService {
@Autowired
private AsyncService asyncService;
public void callAsyncMethod() {
asyncService.asyncMethod();
System.out.println("主线程继续执行");
}
}
七、Spring Boot 如何实现定时任务
7.1 启用定时任务支持
在 Spring Boot 主类上添加 @EnableScheduling
注解:
@SpringBootApplication
@EnableScheduling
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
7.2 创建定时任务方法
在需要定时执行的方法上添加 @Scheduled
注解:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service
public class ScheduledService {
@Scheduled(fixedRate = 5000)
public void fixedRateTask() {
System.out.println("定时任务每隔 5 秒执行一次");
}
@Scheduled(cron = "0 0 12 * * ?")
public void cronTask() {
System.out.println("定时任务每天中午 12 点执行一次");
}
}
八、Spring Boot 如何实现缓存管理
8.1 启用缓存支持
在 Spring Boot 主类上添加 @EnableCaching
注解:
@SpringBootApplication
@EnableCaching
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
8.2 使用缓存注解
在需要缓存的方法上添加 @Cacheable
、@CachePut
、@CacheEvict
等注解:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class CacheService {
@Cacheable("users")
public User getUserById(Long id) {
// 模拟从数据库中查询用户
System.out.println("从数据库中查询用户,ID: " + id);
return new User(id, "John");
}
}
九、Spring Boot 如何实现安全认证
9.1 添加 Spring Security 依赖
在 pom.xml
中添加 Spring Security 的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
9.2 配置安全认证
创建一个配置类,继承 WebSecurityConfigurerAdapter
类,并覆盖 configure
方法:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
9.3 创建用户和角色
在配置类中创建用户和角色:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("password"))
.roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
十、Spring Boot 热部署原理及实现
10.1 热部署原理
Spring Boot 热部署的原理是通过使用 Spring Loaded 或 DevTools 来实现的。当代码发生变化时,热部署工具会重新加载类,而不需要重启整个应用。
10.2 使用 DevTools 实现热部署
在 pom.xml
中添加 DevTools 的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
当我们修改代码后,IDE 会自动编译代码,DevTools 会检测到类文件的变化,并重新加载修改后的类。
10.3 注意事项
- DevTools 会在开发环境中自动生效,生产环境中不会生效。
- 某些情况下,如修改配置文件,可能需要手动重启应用。