2024年 Java 面试八股文——SpringBoot篇

发布于:2024-05-06 ⋅ 阅读:(36) ⋅ 点赞:(0)

目录

1. 什么是 Spring Boot?

2. 为什么要用SpringBoot

3. SpringBoot与SpringCloud 区别

4. Spring Boot 有哪些优点?

5. Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

6. Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?

7. SpringBoot Starter的工作原理

8. Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?

9. SpringBoot支持什么前端模板,

10. SpringBoot的缺点

11. 运行 Spring Boot 有哪几种方式?

12. Spring Boot 需要独立的容器运行吗?

13. 开启 Spring Boot 特性有哪几种方式?

14. SpringBoot 实现热部署有哪几种方式?

15. SpringBoot事物的使用

16. Async异步调用方法

17. 如何在 Spring Boot 启动的时候运行一些特定的代码?

18. Spring Boot 有哪几种读取配置的方式?

19. 什么是 JavaConfig?

20. SpringBoot的自动配置原理是什么

21. 你如何理解 Spring Boot 配置加载顺序?

22. 什么是 YAML?

23. YAML 配置的优势在哪里 ?

24. Spring Boot 是否可以使用 XML 配置 ?

25. spring boot 核心配置文件是什么?bootstrap.properties 和application.properties 有何区别 ?

26. 什么是 Spring Profiles?

27. SpringBoot多数据源拆分的思路

28. SpringBoot多数据源事务如何管理

29. 保护 Spring Boot 应用有哪些方法?

30. 如何实现 Spring Boot 应用程序的安全性?

31. 比较一下 Spring Security 和 Shiro 各自的优缺点 ?

32. Spring Boot 中如何解决跨域问题 ?

33. Spring Boot 中的监视器是什么?

34. 如何使用 Spring Boot 实现全局异常处理?

35. 我们如何监视所有 Spring Boot 微服务?

36. SpringBoot性能如何优化

37. 如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?Spring Boot项目如何热部署?

38. SpringBoot微服务中如何实现 session 共享 ?

39. 您使用了哪些 starter maven 依赖项?

40. Spring Boot 中的 starter 到底是什么 ?


SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。这个框架通过使用特定的配置方式,使得开发人员不再需要定义样板化的配置,从而能够专注于业务代码的开发,提高开发效率。

注:喜欢的朋友可以关注公众号“JAVA学习课堂”方便阅读,内容同步更新。

1. 什么是 Spring Boot?

Spring Boot 是一个由 Pivotal 团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。它基于Spring框架,提供了快速开发Spring应用的脚手架,帮助开发者避免编写大量样板代码和配置文件。

2. 为什么要用SpringBoot

  • 快速开发,快速整合,配置简化、内嵌服务容器

3. SpringBoot与SpringCloud 区别

  • SpringBoot:更关注于单个微服务的快速开发和部署,提供了丰富的工具和特性来简化这一过程。
  • SpringCloud:更关注于微服务之间的协作和治理,提供了一套完整的微服务解决方案,包括服务发现、配置管理、熔断降级等。

4. Spring Boot 有哪些优点?

Spring Boot 主要有如下优点:

  1. 容易上手,提升开发效率,为 Spring 开发提供一个更快、更简单的开发框架。
  2. 开箱即用,远离繁琐的配置。
  3. 提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。
  4. SpringBoot总结就是使编码变简单、配置变简单、部署变简单、监控变简单等等

5. Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

Spring Boot 的核心注解是**@SpringBootApplication**。这个注解实际上是由以下三个注解组成的:

  1. @SpringBootConfiguration:这个注解用于声明一个配置类,表示当前类是一个Spring Boot的配置类,本质上还是@Configuration注解。使用@SpringBootConfiguration注解的类,在功能上也是和@Configuration注解的类一样的,只不过@SpringBootConfiguration注解是Spring Boot特有的一个配置注解。
  2. @EnableAutoConfiguration:这个注解用于启用Spring Boot的自动配置功能。Spring Boot会根据添加的jar包依赖自动配置Spring框架,自动配置的原理是Spring Boot根据添加的jar包依赖来自动配置项目中所需要的配置。
  3. @ComponentScan:这个注解用于告诉Spring Boot扫描哪些包中的组件。默认情况下,Spring Boot会扫描主应用类所在的包以及其子包中的组件。如果需要更改扫描的包路径,可以在@ComponentScan注解中通过basePackages或basePackageClasses属性来指定需要扫描的包路径。

6. Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?

Spring Boot支持多种日志框架,包括Logback、Log4j2、Java Util Logging(JUL)等。这些日志框架可以满足不同的日志需求,具有各自的特点。

在Spring Boot中,默认的日志框架是Logback。Logback是Log4j的继任者,由Log4j的创始人Ceki Gülcü开发,旨在修复Log4j的一些设计缺陷并提供更好的性能。Logback具有以下特点:

  1. 高性能:Logback的性能优于其他日志框架,尤其是在高并发环境下。
  2. 灵活性:Logback支持多种日志输出目的地,如文件、数据库、远程服务器等。
  3. 自动重新加载配置:Logback支持自动重新加载配置文件,无需重启应用。
  4. 丰富的过滤器:Logback提供了丰富的过滤器,可以根据不同的条件过滤日志信息。

除了Logback之外,Log4j2也是Spring Boot支持的一个常用日志框架。Log4j2是Apache开发的一款高性能、灵活的日志框架。尽管Logback是Spring Boot的默认日志框架,但在实际项目中,选择使用哪个日志框架取决于项目的具体需求和个人偏好。

7. SpringBoot Starter的工作原理

SpringBoot Starter的工作原理主要基于以下几个方面:

  1. 起步依赖(Starter Dependencies)
    Starter是Spring Boot提供的一种特殊的Maven或Gradle依赖,它包含了构建某个功能所需的一系列依赖。通过引入相应的Starter,开发者可以快速地添加所需的功能,而无需手动添加每一个依赖。例如,spring-boot-starter-web包含了构建Web应用所需的Servlet API、Spring MVC等依赖。

  2. 自动配置(Auto-configuration)
    Spring Boot的自动配置功能是其核心特性之一。在引入Starter之后,Spring Boot会根据项目中的类路径、配置文件(如application.propertiesapplication.yml)以及环境变量等信息,自动地配置Spring应用上下文(ApplicationContext)。这些自动配置是基于Spring的条件化配置(Conditional Configuration)实现的,即根据一定的条件(如类路径中是否存在某个类、某个配置项的值等)来决定是否加载某个配置。

  3. 约定大于配置(Convention Over Configuration)
    Spring Boot遵循“约定大于配置”的原则,即尽可能多地使用默认值和约定来简化配置。这意味着在大多数情况下,开发者只需要引入相应的Starter并编写业务代码,而无需进行繁琐的配置。当然,如果需要自定义配置,Spring Boot也提供了丰富的配置项供开发者选择。

8. Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?

  1. Spring Framework 版本
    • Spring Boot 2.X 构建在 Spring Framework 5.X 之上,而 Spring Boot 1.X 版本则构建在 Spring Framework 4.X 之上。这一升级使得 Spring Boot 2.X 能够提供最新的 Spring 框架功能,并支持 Java 8 及更高版本。
  2. 响应式编程支持
    • Spring Boot 2.X 引入了响应式编程模型,通过整合 Spring WebFlux 和 Reactor 等项目,提供了对响应式编程的支持。这使得开发人员能够构建高性能、高吞吐量的非阻塞应用程序。在 1.X 版本中,Spring MVC 使用的是同步的 Servlet API,而在 2.X 版本中,可以选择使用响应式的 WebFlux 框架。
  3. 自动配置的改进
    • Spring Boot 2.X 在自动配置方面进行了许多改进。在 1.X 版本中,自动配置是基于条件的,通过一系列的条件判断来确定是否应该应用某个配置。而在 2.X 版本中,引入了条件注解的改进,可以根据一组条件来自动配置应用程序,这进一步简化了配置过程。
  4. Web安全性增强
    • Spring Boot 2.X 在 Web 安全性方面进行了增强。它引入了许多新的特性和改进,以帮助开发者更容易地实现安全性需求。其中一个重要的改进是引入了 PasswordEncoder 接口,用于密码的加密和验证。
  5. Web容器
    • Spring Boot 2.X 默认使用 Tomcat 8.5 或以上版本作为嵌入式 Web 容器,而 Spring Boot 1.X 默认使用 Tomcat 7。
  6. 配置文件的改进
    • 在 Spring Boot 2.X 中,配置文件的中文可以直接读取,而不需要进行转码。这简化了国际化配置的过程。
  7. 其他改进
    • Spring Boot 2.X 还对 JPA、MVC、错误处理等方面进行了改进。例如,在 JPA 中,findById 方法返回了一个 Optional 对象,这可能会影响业务代码。在 MVC 部分,WebMvcConfigurer 由抽象类改为接口,以适应 JDK 8 对接口的新支持形式。

9. SpringBoot支持什么前端模板

SpringBoot支持多种前端模板,包括但不限于以下几种:

  1. Thymeleaf:Thymeleaf是一种服务器端Java模板引擎,能够在服务器端生成HTML。它与Spring Boot紧密集成,提供了丰富的特性和表达式语言,使得开发人员能够轻松地构建动态的、可交互的Web页面。Thymeleaf既是原型又是页面,开发速度更快,符合Spring Boot的理念。
  2. Freemarker:Freemarker是另一个流行的Java模板引擎,它允许你在HTML模板中嵌入Java代码,以生成动态内容。Freemarker具有灵活的模板语法和强大的数据处理能力。
  3. Velocity:Velocity是另一个与Spring Boot兼容的模板引擎。它提供了一种简单的模板语言,用于在Web应用程序中生成动态内容。Velocity的语法类似于Java,易于学习和使用。

10. SpringBoot的缺点

尽管Spring Boot带来了许多优点,如快速构建Spring应用、简化配置、提供自动配置等,但它也有一些潜在的缺点和限制。以下是一些关于SpringBoot的缺点:

  1. 学习曲线:对于初学者来说,Spring Boot的生态系统可能显得庞大和复杂。它涉及许多组件、库和依赖项,需要花费一定的时间和精力来学习和理解。

  2. 过度封装:Spring Boot的自动配置和约定大于配置的原则可能会导致一些过度封装。在某些情况下,这可能会使开发人员难以理解和控制底层细节,如数据源配置、事务管理等。

  3. 依赖管理:Spring Boot通过Maven或Gradle等构建工具管理依赖项。然而,随着项目的增长,依赖项的数量可能会变得庞大,这可能会导致依赖冲突、版本不兼容等问题。此外,Spring Boot的默认依赖项可能不适用于所有项目,需要手动排除或添加额外的依赖项。

  4. 性能开销:虽然Spring Boot简化了开发和部署过程,但它也引入了一定的性能开销。这主要是由于Spring框架本身的复杂性以及运行时环境的开销所致。对于需要高性能的应用程序,可能需要考虑其他轻量级的框架或优化SpringBoot的配置。

  5. 社区支持:虽然Spring Boot拥有庞大的社区和广泛的支持,但这也可能导致信息过载。在寻找解决方案或解答问题时,可能会面临大量的文档、教程和讨论,需要花费一定的时间和精力来筛选和评估。

  6. 不易于迁移:一旦项目使用Spring Boot构建并依赖其生态系统中的多个组件和库,将其迁移到其他框架或平台可能会变得困难。这可能会导致技术锁定和限制未来的技术选择。

  7. 配置复杂性:虽然Spring Boot提供了自动配置和默认配置,但在某些情况下,仍然需要手动配置和调整各种设置。这可能会增加配置的复杂性,并需要开发人员具备更深入的知识和经验。

11. 运行 Spring Boot 有哪几种方式?

运行Spring Boot有几种常见的方式,以下是其中几种主要的方法:

  1. 直接启动
    • 这是最直接简单的方式,通常通过集成开发环境(IDE)如IntelliJ IDEA、Eclipse等,直接运行Spring Boot应用程序的启动类(通常是包含main方法的类,并标注有@SpringBootApplication注解)。
  2. 使用Maven或Gradle命令运行
    • 对于使用Maven构建的项目,可以在项目目录下执行mvn spring-boot:run命令来运行Spring Boot应用程序。
    • 对于使用Gradle构建的项目,也有相应的Gradle命令来运行应用程序。
  3. 打包成可执行的JAR文件运行
    • 可以将Spring Boot应用程序打包成可执行的JAR文件,然后通过java -jar your-app.jar命令来运行。这种方式便于部署和分发,因为JAR文件是跨平台的。
  4. 打包成WAR文件并部署到Servlet容器运行
    • 如果需要将Spring Boot应用程序部署到传统的Servlet容器(如Tomcat、Jetty等),可以将应用程序打包成WAR文件,然后将WAR文件部署到Servlet容器中运行。但请注意,Spring Boot 2.x版本默认是不支持WAR部署的,需要进行一些配置。
  5. 使用Docker容器运行
    • 可以将Spring Boot应用程序打包为Docker镜像,并在Docker容器中运行。这种方式可以方便地实现应用的容器化部署和管理。
  6. 自定义运行
    • 在某些特殊场景下,可能需要自定义运行Spring Boot应用程序的方式。例如,可以通过复制BOOT-INF/lib至BOOT-INF/classes中,并编写脚本命令来单独启动服务。

12. Spring Boot 需要独立的容器运行吗?

  • 可以不需要,内置了 Tomcat/ Jetty 等容器。

13. 开启 Spring Boot 特性有哪几种方式?

  1. 继承spring-boot-starter-parent项目
  2. 导入spring-boot-dependencies项目依赖

14. SpringBoot 实现热部署有哪几种方式?

SpringBoot实现热部署的几种方式包括:

  1. 使用Spring Boot Devtools
    • Spring Boot Devtools是一个为开发者提供的工具集,它提供了自动重新加载类和配置文件更改的功能。只需在Spring Boot项目中添加spring-boot-devtools依赖,就可以实现页面和代码的热部署。但这种方式主要是采用文件变化后重启的策略来实现,所以在体验上可能会稍差一些。
  2. 使用JRebel
    • JRebel是一个流行的热部署工具,可以与Spring Boot配合使用。它可以在不重启应用的情况下,实时更新代码和配置。
  3. 使用Spring Boot Admin
    • Spring Boot Admin是一个用于管理和监控Spring Boot应用的开源工具。虽然它本身并不直接提供热部署功能,但它可以与Devtools或其他热部署工具配合使用,来增强应用的管理和监控能力。
  4. 使用自定义热部署插件
    • 如果以上方法不满足特定需求,开发人员还可以编写自定义的热部署插件。例如,可以创建一个Maven或Gradle插件,实现在编译和打包项目时自动更新应用程序。
  5. 使用持续集成/持续部署(CI/CD)工具
    • 现代软件开发团队通常使用CI/CD工具(如Jenkins、Travis CI等)来实现自动化构建、测试和部署流程。这些工具可以与热部署工具配合使用,以在代码更改时自动触发构建、测试和部署流程。
  6. 使用Spring Loaded
    • Spring Loaded是一种与Debug模式类似但又不依赖于Debug模式启动的热部署方式。通过Spring Loaded库文件启动应用,可以在正常模式下进行实时热部署。

15. SpringBoot事物的使用

在Spring Boot中,事务的管理通常是通过Spring框架的事务管理功能来实现的。Spring框架提供了一种声明式的事务管理,这使得事务管理变得简单且易于配置。以下是Spring Boot中事务使用的基本步骤和概念:

  1. 添加依赖
    首先,确保你的Spring Boot项目中包含了Spring Data JPA或MyBatis等持久层框架的依赖,以及Spring Boot的spring-boot-starter-data-jpaspring-boot-starter-jdbc等依赖,这些依赖会包含Spring事务管理所需的基础功能。

  2. 配置数据源
    application.propertiesapplication.yml文件中配置你的数据源信息,如数据库URL、用户名、密码等。Spring Boot会自动根据这些配置创建数据源,并将其注入到你的持久层组件中。

  3. 开启事务管理
    在你的Spring Boot应用中,通常需要在配置类上添加@EnableTransactionManagement注解来开启事务管理功能。但在Spring Boot中,由于它自动配置的特性,这个注解通常不是必需的。如果你使用的是JPA或MyBatis等持久层框架,它们通常会默认开启事务管理。

  4. 声明事务边界
    在你的业务逻辑代码中,使用@Transactional注解来声明事务的边界。这个注解可以标注在类上或方法上。当标注在类上时,表示该类中的所有方法都使用相同的事务配置;当标注在方法上时,表示只有该方法使用特定的事务配置。@Transactional注解提供了许多属性,用于配置事务的传播行为、隔离级别、超时时间等。

  5. 处理异常
    在事务方法中,如果发生了运行时异常(RuntimeException)或Error,Spring会默认回滚事务。如果你希望在其他类型的异常发生时也回滚事务,可以在@Transactional注解中通过rollbackFor属性指定异常类型。

  6. 使用事务模板
    除了使用@Transactional注解外,你还可以使用PlatformTransactionManager接口和TransactionTemplate类来编程式地管理事务。这种方式通常在你需要更细粒度地控制事务边界或逻辑时使用。

  7. 测试
    在开发过程中,确保对涉及事务的业务逻辑进行充分的测试,以确保事务的正确性和可靠性。你可以使用Spring Boot的测试框架(如JUnit和Spring Test)来编写集成测试或单元测试。

16. Async异步调用方法

在Spring Boot中,@Async 注解是用于异步执行方法的。当方法被@Async注解标注时,它将在单独的线程中异步执行,而不是在调用它的线程中同步执行。这对于提高应用程序的响应性和吞吐量非常有用,特别是当你有一些耗时的任务需要执行时。

以下是使用@Async注解进行异步调用的基本步骤:

  1. 启用异步支持
    在Spring Boot应用程序的主类或配置类上添加@EnableAsync注解,以启用异步支持。

    @SpringBootApplication  
    @EnableAsync  
    public class MySpringBootApplication {  
        public static void main(String[] args) {  
            SpringApplication.run(MySpringBootApplication.class, args);  
        }  
    }

  2. 配置线程池(可选):
    默认情况下,Spring使用SimpleAsyncTaskExecutor来异步执行任务,但这不是生产环境中推荐的做法,因为它不会重用线程。通常,你会希望配置一个TaskExecutor来管理异步任务的线程池。

    @Configuration  
    @EnableAsync  
    public class AsyncConfig implements AsyncConfigurer {  
          
        @Override  
        public Executor getAsyncExecutor() {  
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();  
            executor.setCorePoolSize(5);  
            executor.setMaxPoolSize(10);  
            executor.setQueueCapacity(25);  
            executor.initialize();  
            return executor;  
        }  
          
        // 还可以配置异步方法的异常处理器  
        @Override  
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {  
            return new AsyncUncaughtExceptionHandler() {  
                @Override  
                public void handleUncaughtException(Throwable ex, Method method, Object... params) {  
                    // 处理异常  
                }  
            };  
        }  
    }

  3. 使用@Async注解
    在需要异步执行的方法上添加@Async注解。这个方法可以是在Spring管理的Bean中的任何方法。

    @Service  
    public class MyAsyncService {  
          
        @Async  
        public void asyncMethod() {  
            // 异步执行的代码  
            System.out.println("Executing async method.");  
            // 模拟耗时操作  
            try {  
                Thread.sleep(3000);  
            } catch (InterruptedException e) {  
                Thread.currentThread().interrupt();  
            }  
            System.out.println("Async method completed.");  
        }  
    }

  4. 调用异步方法
    在应用程序的其他部分,你可以像调用普通方法一样调用异步方法,但它将在一个新的线程中执行。

@RestController  
public class MyController {  
      
    @Autowired  
    private MyAsyncService myAsyncService;  
      
    @GetMapping("/startAsync")  
    public String startAsyncProcess() {  
        myAsyncService.asyncMethod(); // 异步执行  
        return "Async process started.";  
    }  
}

请注意,由于异步方法是在单独的线程中执行的,因此它不会阻塞调用它的线程。这意味着在上面的例子中,startAsyncProcess 方法会立即返回,而asyncMethod 将在另一个线程中继续执行。

此外,还需要注意异常处理。由于异步方法是在不同的线程中执行的,因此任何在异步方法中抛出的未捕获异常都不会传播到调用它的线程。这就是为什么在AsyncConfig中提供了getAsyncUncaughtExceptionHandler方法的原因,你可以在这里定义如何处理这些异常。

17. 如何在 Spring Boot 启动的时候运行一些特定的代码?

在Spring Boot中,有几种方式可以在应用启动时运行特定的代码。以下是一些常见的方法:

  1. 使用@PostConstruct注解

    你可以在一个Bean的某个方法上使用@PostConstruct注解,这样该方法就会在Spring容器初始化该Bean之后立即被调用。

    @Component  
    public class StartupRunner {  
    
        @PostConstruct  
        public void runOnStartup() {  
            // 你的启动代码  
        }  
    }

  2. 实现CommandLineRunnerApplicationRunner接口

    实现这两个接口中的任何一个,并在run方法中编写你的启动代码。Spring Boot会在所有Spring Beans都初始化完成后调用这些方法。CommandLineRunner接收一个String数组作为参数(通常是命令行参数),而ApplicationRunner接收一个ApplicationArguments对象,它提供了对命令行参数的更强大访问。

    @Component  
    public class MyStartupRunner implements CommandLineRunner {  
    
        @Override  
        public void run(String... args) throws Exception {  
            // 你的启动代码  
        }  
    }
     

    或者

    @Component  
    public class MyApplicationRunner implements ApplicationRunner {  
    
        @Override  
        public void run(ApplicationArguments args) throws Exception {  
            // 你的启动代码  
        }  
    }
     

    你可以定义多个CommandLineRunnerApplicationRunner,并且可以通过在类上添加@Order注解或使用@Component@Order属性来指定它们的执行顺序。

  3. 使用@EventListener注解监听ApplicationReadyEvent

    除了使用CommandLineRunnerApplicationRunner之外,你还可以创建一个Bean来监听ApplicationReadyEvent事件。这个事件在Spring Boot完成所有应用程序和Spring Beans的初始化并准备处理HTTP请求之后触发。

    @Component  
    public class MyEventListener {  
    
        @EventListener(ApplicationReadyEvent.class)  
        public void handleApplicationReadyEvent() {  
            // 你的启动代码  
        }  
    }

  4. 通过继承SpringBootServletInitializer(用于非Web应用可能不适用)

    如果你的应用是一个Spring Boot WAR包并部署到传统的Servlet容器中,你可以通过继承SpringBootServletInitializer并覆盖onStartup方法来在应用启动时执行代码。但是,请注意这种方法通常用于Web应用的Servlet容器初始化,而不是Spring Boot应用的自动配置和启动。

  5. main方法中

    虽然不推荐在main方法中直接编写启动代码(因为这可能会与Spring Boot的自动配置冲突),但你可以在SpringApplication.run调用前后编写代码,以执行一些必须在Spring容器初始化之前或之后运行的逻辑。

    @SpringBootApplication  
    public class MyApplication {  
    
        public static void main(String[] args) {  
            // 在Spring容器初始化之前执行的代码  
    
            SpringApplication app = new SpringApplication(MyApplication.class);  
            app.run(args);  
    
            // 在Spring容器初始化之后执行的代码(但通常不推荐这样做)  
        }  
    }
     

    请注意,在main方法之后执行的代码可能不是最佳实践,因为它可能会错过Spring Boot的一些事件和回调。

18. Spring Boot 有哪几种读取配置的方式?

Spring Boot 提供了多种读取配置文件的方式,以下是一些主要的方法:

  1. 使用@Value注解
    在Spring Boot中,你可以使用@Value注解从配置文件(如application.propertiesapplication.yml)中注入属性值到类的字段中。

    @RestController  
    public class MyController {  
    
        @Value("${person.name}")  
        private String name;  
    
        @Value("${person.age}")  
        private int age;  
    
        // ... 其他代码  
    }
  2. 使用@ConfigurationProperties注解
    这个注解可以将整个配置文件的属性绑定到一个Java对象上,这对于处理具有多个属性的复杂配置特别有用。

    @Component  
    @ConfigurationProperties(prefix = "person")  
    public class PersonProperties {  
    
        private String name;  
        private int age;  
    
        // getter 和 setter ...  
    }
    使用Environment接口
  3. Environment接口提供了对Spring Boot当前环境的访问,包括属性源和配置文件。你可以注入Environment对象并调用其方法来访问属性。

    @Component  
    public class MyComponent {  
    
        private final Environment env;  
    
        public MyComponent(Environment env) {  
            this.env = env;  
        }  
    
        public void doSomething() {  
            String name = env.getProperty("person.name");  
            // ... 其他代码  
        }  
    }
  4. 使用@PropertySource注解
    这个注解允许你指定一个或多个额外的属性文件,以便在@Configuration类中使用。这对于将配置分散到多个文件中特别有用。

    @Configuration  
    @PropertySource("classpath:my-config.properties")  
    public class MyConfig {  
    
        // ... 其他代码  
    }

  5. 通过命令行参数
    Spring Boot允许你在启动应用程序时通过命令行参数传递属性。这些参数会覆盖在配置文件中定义的属性。

    java -jar myapp.jar --person.name=John --person.age=30

  6. 使用Spring Profiles
    Spring Profiles允许你根据不同的环境(如开发、测试、生产)定义不同的配置。你可以通过spring.profiles.active属性或在命令行中指定激活哪个Profile。

    java -jar myapp.jar --spring.profiles.active=prod
  7. 使用@Conditional系列注解
    虽然这不是直接读取配置文件的方式,但@Conditional系列注解(如@ConditionalOnProperty)允许你根据配置文件的属性条件化地创建Bean。

19. 什么是 JavaConfig?

Spring JavaConfig 的优点

  1. 面向对象的配置:JavaConfig 允许使用 Java 类和面向对象的概念(如继承、组合、多态等)来配置 Spring 容器。这使得配置更加直观和易于理解。

  2. 减少或消除 XML 配置:JavaConfig 提供了纯 Java 的配置方式,从而避免了 XML 配置的繁琐和错误。当然,JavaConfig 和 XML 可以混合使用,但许多开发者倾向于只使用 JavaConfig。

  3. 类型安全和重构友好:JavaConfig 利用 Java 的类型安全特性,确保在编译时就能发现配置错误。此外,由于它是基于 Java 的,因此可以与 IDE 的重构工具无缝集成。

  4. 可读性和可维护性:JavaConfig 配置通常比 XML 配置更易于阅读和维护,因为它们使用了熟悉的 Java 语法和语义。

常用的 JavaConfig 注解

  1. @Configuration:这个注解表明一个类是一个配置类,用于定义 bean 和导入其他配置类。

  2. @ComponentScan:这个注解用于自动扫描和注册配置类所在的包(以及子包)中的组件(如 @Component、@Service、@Repository、@Controller 等)。

  3. @Bean:这个注解用于在配置类中定义一个 bean。方法名通常用作 bean 的名称,但也可以通过 @Bean 注解的 name 属性指定其他名称。方法的返回类型就是 bean 的类型。

  4. @EnableWebMvc:这个注解用于启用 Spring MVC 的特性,如注解驱动的控制器、视图解析等。通常与 @Configuration 注解一起使用在配置类中。

  5. @ImportResource:虽然 JavaConfig 旨在替代 XML 配置,但有时可能还需要加载一些 XML 配置文件。这个注解允许你在 JavaConfig 类中导入 XML 配置文件。

  6. @PropertySource:这个注解用于加载 .properties 文件中的属性,这些属性可以在配置类中使用 @Value 注解注入到字段或方法参数中。

  7. @Profile:这个注解用于定义特定环境的配置。例如,你可能有一个用于开发环境的配置和一个用于生产环境的配置。通过激活相应的 profile,可以加载不同的配置。

  8. @Conditional:这个注解(以及相关的条件注解,如 @ConditionalOnClass@ConditionalOnProperty 等)允许你根据条件决定是否创建 bean。这对于根据环境或依赖项的存在性来配置应用程序非常有用。

20. SpringBoot的自动配置原理是什么

  1. 主配置类与@SpringBootApplication注解
    • 应用程序的入口是一个带有@SpringBootApplication注解的类。这个注解实际上是@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan三个注解的组合。
    • @SpringBootConfiguration表明该类是一个配置类,允许使用@Bean注解定义bean。
    • @EnableAutoConfiguration告诉Spring Boot根据添加的jar依赖来自动配置Spring应用上下文。
    • @ComponentScan则让Spring Boot扫描当前包及其子包下被@Component@Service@Repository@Controller等注解标记的类,并注册为bean。
  2. 加载META-INF/spring.factories文件
    • Spring Boot在启动时,会扫描classpath下所有META-INF/spring.factories文件。
    • 这些文件包含了Spring Boot自动配置类的列表,这些类会根据应用程序的需要进行加载和配置。
  3. 去重和排除
    • 对于从spring.factories文件中加载到的自动配置类列表,Spring Boot会进行去重处理。
    • 同时,可以通过@SpringBootApplicationexcludeexcludeName属性,或者spring.autoconfigure.exclude属性,来排除不需要的自动配置类。
  4. 条件化配置
    • Spring Boot使用@Conditional注解及其派生注解(如@ConditionalOnClass@ConditionalOnProperty等)来决定是否应该加载某个自动配置类。
    • 这些条件基于类路径、属性设置、Bean的存在性等来评估,确保只有在满足特定条件时才会应用自动配置。
  5. 创建和注册Bean
    • 对于满足条件的自动配置类,Spring Boot会创建其定义的Bean,并将其注册到Spring应用上下文中。
    • 这些Bean可以包括各种组件、服务、数据源、消息队列等,为应用程序提供所需的功能。
  6. 外部化配置
    • Spring Boot支持外部化配置,允许通过application.propertiesapplication.yml文件来覆盖自动配置的默认值。
    • 这些配置文件可以位于不同的位置,如项目的类路径、用户的主目录、命令行参数等。
    • 外部化配置允许开发人员更灵活地配置应用程序,以满足不同的环境和需求。

21. 你如何理解 Spring Boot 配置加载顺序?

Spring Boot的配置加载顺序主要基于以下几个因素:

  1. 默认配置:首先,Spring Boot会加载默认的配置,这些配置通常包含在Spring Boot的源代码中。
  2. 属性配置(Property Sources):接下来,Spring Boot会加载通过@PropertySource注解指定的外部属性文件。这些属性文件可以是.properties.yml格式,并且可以在配置类中使用@PropertySource注解进行指定。
  3. Servlet初始化参数配置:如果应用程序是一个基于Servlet的Web应用程序,那么Servlet的初始化参数(通过web.xml或Servlet API的setInitParameter方法设置)也会被加载。
  4. Servlet上下文参数配置:Servlet的全局上下文参数(同样可以通过web.xml或Servlet API进行设置)也会被加载。
  5. 系统属性配置:通过System.setProperty()方法设置的系统属性也会被加载。
  6. 系统环境变量配置:系统环境变量(如classpathpath等)也会被考虑在内。
  7. 随机值配置:在某些情况下,Spring Boot可能会使用随机值来配置某些属性。
  8. 激活的配置文件:Spring Boot会根据激活的配置文件(如application-dev.propertiesapplication-prod.properties等)进行加载。这些配置文件的激活通常通过spring.profiles.active属性进行设置。
  9. 命令行参数:最后,Spring Boot会考虑命令行参数。例如,你可以使用--spring.config.location=C:/application.properties来指定一个特定的配置文件位置。

在以上配置加载的过程中,高优先级的配置会覆盖低优先级的配置。具体来说,如果在多个配置文件中对同一个属性进行了配置,那么最后加载的配置文件中的属性值将覆盖先前加载的配置文件中的属性值。

22. 什么是 YAML?

  • YAML 是一种人类可读的数据序列化语言。它通常用于配置文件。与属性文件相比,如果我们想要
    在配置文件中添加复杂的属性,YAML 文件就更加结构化,而且更少混淆。可以看出 YAML 具有分
    层配置数据。

23. YAML 配置的优势在哪里 ?

  1. YAML 现在可以算是非常流行的一种配置文件格式了,无论是前端还是后端,都可以见到 YAML 配置。
    1.  配置有序,在一些特殊的场景下,配置有序很关键
    2.  简洁明了,他还支持数组,数组中的元素可以是基本数据类型也可以是对象
    3. 相比 properties 配置文件,YAML 还有一个缺点,就是不支持 @PropertySource 注解导入
    4. 自定义的 YAML 配置。

24. Spring Boot 是否可以使用 XML 配置 ?

  • Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通
    过 @ImportResource 注解可以引入一个 XML 配置。

25. spring boot 核心配置文件是什么?bootstrap.properties 和application.properties 有何区别 ?

Spring Boot 的核心配置文件主要有两种:bootstrap.properties(或bootstrap.yml)和application.properties(或application.yml)。它们之间的主要区别体现在加载顺序、用途和配置环境上。

  1. 加载顺序
    • bootstrap.properties(或bootstrap.yml)由父ApplicationContext加载,并且在application.properties(或application.yml)之前加载。这意味着bootstrap中的配置会优先于application中的配置。
    • application.properties(或application.yml)由ApplicationContext加载,并在bootstrap之后加载。
  2. 用途
    • bootstrap.properties主要用于在应用程序上下文的引导阶段加载配置,比如当使用Spring Cloud时,配置服务(如Config Server)的位置通常需要在bootstrap阶段就确定,以便在application阶段可以从远程配置服务器加载配置。另外,bootstrap中的配置通常是一些固定的、不能被覆盖的属性,以及加密/解密的场景。
    • application.properties主要用于配置应用程序的属性,如端口号、数据库连接、日志级别等。这些配置可以根据不同的环境(如开发、测试、生产)进行不同的设置。
  3. 配置环境
    • bootstrap.propertiesbootstrap.yml主要用于配置那些需要在应用程序上下文引导阶段就加载的属性,比如配置中心的位置、版本控制信息等。
    • application.propertiesapplication.yml则主要用于配置那些与应用程序运行紧密相关的属性,比如数据源、服务器端口、日志配置等。

总的来说,bootstrap.propertiesapplication.properties的主要区别在于它们的加载顺序和用途。在需要早期加载配置或需要从远程配置服务器加载配置时,通常使用bootstrap.properties;而在配置应用程序的运行属性时,通常使用application.properties

26. 什么是 Spring Profiles?

Spring Profiles是Spring框架中一种用于定义不同配置环境的机制,它允许开发者根据不同的环境(如开发环境、测试环境、生产环境等)来配置不同的Bean、属性和配置,从而实现在不同环境下应用程序的定制化配置。

Spring Profiles的主要作用包括:

  1. 根据环境加载不同配置:通过定义不同的Profiles,可以根据不同的环境需求加载不同的配置文件。
  2. 激活不同的Bean:可以根据不同的Profiles来激活或禁用特定的Bean,从而根据不同的环境需求定制应用程序的行为。
  3. 简化开发和测试:通过使用Spring Profiles,可以简化开发和测试过程,方便在不同环境下进行配置和调试。

在Spring Boot中,Spring Profiles可以通过@Profile注解或application-{profile}.properties文件来定义和激活。例如,spring.profiles.active=dev会启用application-dev.yml配置文件。同时,@Profile注解可以应用于类级别或方法级别,用于指定某个类或方法只在特定Profile下生效。

以上信息仅供参考,如有需要,建议查阅Spring官方文档或相关书籍。

27. SpringBoot多数据源拆分的思路

SpringBoot多数据源拆分的思路主要涉及到如何在一个Spring Boot应用中配置和管理多个数据源。以下是一个基本的拆分思路:

  1. 定义数据源配置
    首先,你需要在Spring Boot的配置文件中(如application.ymlapplication.properties)为每个数据源定义配置。这包括数据库的URL、用户名、密码、驱动类名等。你可以使用前缀或命名空间来区分不同的数据源配置,如datasource1datasource2等。

    例如,在application.yml中:

    spring:  
      datasource:  
        datasource1:  
          url: jdbc:mysql://localhost:3306/db1  
          username: user1  
          password: pass1  
          driver-class-name: com.mysql.cj.jdbc.Driver  
        datasource2:  
          url: jdbc:mysql://localhost:3306/db2  
          username: user2  
          password: pass2  
          driver-class-name: com.mysql.cj.jdbc.Driver

  2. 创建数据源Bean
    接下来,你需要为每个数据源创建一个DataSource Bean。这可以通过Java配置类或使用@ConfigurationProperties注解来实现。在Java配置类中,你可以使用@Bean注解来定义数据源Bean,并使用@ConfigurationProperties来绑定配置文件中的属性。

    例如:

    @Configuration  
    @EnableConfigurationProperties({DataSourceProperties1.class, DataSourceProperties2.class})  
    public class DataSourceConfig {  
    
        @Bean(name = "datasource1")  
        @ConfigurationProperties(prefix = "spring.datasource.datasource1")  
        public DataSource dataSource1(DataSourceProperties1 properties) {  
            return properties.initializeDataSourceBuilder().build();  
        }  
    
        // 同样地,为datasource2配置Bean...  
    }  
    
    // DataSourceProperties1和DataSourceProperties2是自定义的配置属性类,用于绑定配置文件中的属性。

  3. 配置数据源路由
    在多个数据源的情况下,你需要一种机制来根据业务逻辑或请求上下文选择使用哪个数据源。这可以通过实现AbstractRoutingDataSource类或使用第三方库(如dynamic-datasource-spring-boot-starter)来实现。

    如果你选择实现AbstractRoutingDataSource,你需要重写determineCurrentLookupKey()方法来返回当前线程的数据源键。这个键应该与你在Java配置类中定义的数据源Bean的名称相对应。

  4. 事务管理
    当使用多个数据源时,你需要为每个数据源配置独立的事务管理器。这可以通过为每个数据源创建一个PlatformTransactionManager Bean来实现。

  5. MyBatis或其他ORM框架配置
    如果你的应用使用MyBatis或其他ORM框架,你需要为每个数据源配置独立的SqlSessionFactory或EntityManagerFactory。这可以通过在MyBatis的配置文件中指定不同的数据源Bean或使用Java配置类来实现。

  6. 使用数据源
    最后,在你的服务层或DAO层中,你可以通过@Qualifier注解或@Autowired注解(结合@Primary或自定义的Qualifier)来注入你需要的数据源。然后,你可以像使用单个数据源一样使用这些数据源来执行数据库操作。。

28. SpringBoot多数据源事务如何管理

在Spring Boot中管理多数据源的事务,你需要为每个数据源配置独立的事务管理器,并在需要的时候指定使用哪个事务管理器来执行事务。以下是如何管理多数据源事务的基本步骤:

  1. 配置数据源
    首先,你需要在Spring Boot的配置文件中(如application.ymlapplication.properties)为每个数据源定义配置,并在Java配置类中为每个数据源创建DataSource Bean。

  2. 配置事务管理器
    为每个数据源配置一个独立的事务管理器。你可以使用JpaTransactionManager(如果你使用JPA)或DataSourceTransactionManager(如果你使用JDBC)作为事务管理器。

    @Bean(name = "transactionManager1")  
    public PlatformTransactionManager transactionManager1(@Qualifier("dataSource1") DataSource dataSource1) {  
        return new DataSourceTransactionManager(dataSource1);  
    }  
    
    // 为第二个数据源配置类似的事务管理器  
    @Bean(name = "transactionManager2")  
    public PlatformTransactionManager transactionManager2(@Qualifier("dataSource2") DataSource dataSource2) {  
        return new DataSourceTransactionManager(dataSource2);  
    }

  3. 指定事务管理器
    在你的服务层或DAO层中,使用@Transactional注解时,你需要通过transactionManager属性来指定使用哪个事务管理器。

    @Service  
    public class MyService {  
    
        @Autowired  
        @Qualifier("transactionManager1")  
        private PlatformTransactionManager transactionManager1;  
    
        // 使用事务管理器1执行事务  
        @Transactional(transactionManager = "transactionManager1")  
        public void myMethodUsingDataSource1() {  
            // ... 业务逻辑  
        }  
    
        // 为第二个数据源的服务方法配置类似的事务管理  
    }
     

    如果你不想在每个方法上都指定事务管理器,你也可以在类级别上指定,但这将影响类中所有使用@Transactional注解的方法。

  4. 使用@Qualifier注入数据源
    在需要直接操作数据源的DAO层或Repository层,你需要使用@Qualifier注解来注入正确的数据源。

    @Repository  
    public class MyRepository {  
    
        @Autowired  
        @Qualifier("dataSource1")  
        private JdbcTemplate jdbcTemplate1;  
    
        // 使用dataSource1的JdbcTemplate执行数据库操作  
        // ...  
    
        // 为第二个数据源配置类似的JdbcTemplate或其他数据源访问组件  
    }

  5. 处理跨数据源的事务
    如果你的业务逻辑需要跨多个数据源执行事务(即,需要在两个或更多数据源上执行一系列操作,并且它们要作为一个原子操作执行),那么你可能需要实现更复杂的逻辑来确保数据的一致性和完整性。这通常涉及到分布式事务或两阶段提交等复杂机制。

  6. 考虑使用第三方库
    对于多数据源和事务管理,有些第三方库(如dynamic-datasource-spring-boot-starter)提供了更简单的配置和管理方式。这些库可以帮助你更容易地实现多数据源的事务管理。

  7. 测试和验证
    确保对你的多数据源配置和事务管理进行充分的测试和验证,以确保它们按预期工作,并且能够处理各种异常情况。

29. 保护 Spring Boot 应用有哪些方法?

  • 在生产中使用HTTPS
  • 使用Snyk检查你的依赖关系
  • 升级到最新版本
  • 启用CSRF保护
  • 使用内容安全策略防止XSS攻击

30. 如何实现 Spring Boot 应用程序的安全性?

  • 为了实现 Spring Boot 的安全性,我们使用 spring-boot-starter-security 依赖项,并且必须添加安全配置。它只需要很少的代码。配置类将必须扩展WebSecurityConfigurerAdapter 并覆盖其方法。