关于后端:一天吃透SpringBoot面试八股文

49次阅读

共计 9824 个字符,预计需要花费 25 分钟才能阅读完成。

Springboot 的长处

  • 内置 servlet 容器,不须要在服务器部署 tomcat。只须要将我的项目打成 jar 包,应用 java -jar xxx.jar 一键式启动我的项目
  • SpringBoot 提供了 starter,把罕用库聚合在一起,简化简单的环境配置,疾速搭建 spring 应用环境
  • 能够疾速创立独立运行的 spring 我的项目,集成支流框架
  • 准生产环境的运行利用监控

SpringBoot 中的 starter 到底是什么 ?

starter 提供了一个自动化配置类,个别命名为 XXXAutoConfiguration,在这个配置类中通过条件注解来决定一个配置是否失效(条件注解就是 Spring 中本来就有的),而后它还会提供一系列的默认配置,也容许开发者依据理论状况自定义相干配置,而后通过类型平安的属性注入将这些配置属性注入进来,新注入的属性会代替掉默认属性。正因为如此,很多第三方框架,咱们只须要引入依赖就能够间接应用了。

运行 SpringBoot 有哪几种形式?

  1. 打包用命令或者者放到容器中运行
  2. 用 Maven/Gradle 插件运行
  3. 间接执行 main 办法运行

本文曾经收录到 Github 仓库,该仓库蕴含 计算机根底、Java 根底、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享 等外围知识点,欢送 star~

Github 地址

如果拜访不了 Github,能够拜访 gitee 地址。

gitee 地址

SpringBoot 罕用的 Starter 有哪些?

  1. spring-boot-starter-web:提供 Spring MVC + 内嵌的 Tomcat。
  2. spring-boot-starter-data-jpa:提供 Spring JPA + Hibernate。
  3. spring-boot-starter-data-Redis:提供 Redis。
  4. mybatis-spring-boot-starter:提供 MyBatis。

Spring Boot 的外围注解是哪个?

启动类下面的注解是 @SpringBootApplication,它也是 Spring Boot 的外围注解,次要组合蕴含了以下 3 个注解:

  • @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的性能。
  • @EnableAutoConfiguration:关上主动配置的性能,也能够敞开某个主动配置的选项,如敞开数据源主动配置性能:@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})。
  • @ComponentScan:Spring 组件扫描。

主动配置原理

SpringBoot 实现主动配置原理图解:

在 application.properties 中设置属性 debug=true,能够在控制台查看已启用和未启用的主动配置。

@SpringBootApplication 是 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 的组合。

@Configuration 示意该类是 Java 配置类。

@ComponentScan 开启主动扫描符合条件的 bean(增加了 @Controller、@Service 等注解)。

@EnableAutoConfiguration 会依据类门路中的 jar 依赖为我的项目进行主动配置,比方增加了 spring-boot-starter-web 依赖,会主动增加 Tomcat 和 Spring MVC 的依赖,而后 Spring Boot 会对 Tomcat 和 Spring MVC 进行主动配置(spring.factories EnableAutoConfiguration 配置了WebMvcAutoConfiguration)。

给大家分享一个 Github 仓库,下面有大彬整顿的 300 多本经典的计算机书籍 PDF,包含 C 语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生 等,能够 star 一下,下次找书间接在下面搜寻,仓库继续更新中~

Github 地址

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

EnableAutoConfiguration 次要由 @AutoConfigurationPackage,@Import(EnableAutoConfigurationImportSelector.class)这两个注解组成的。

@AutoConfigurationPackage 用于将启动类所在的包外面的所有组件注册到 spring 容器。

@Import 将 EnableAutoConfigurationImportSelector 注入到 spring 容器中,EnableAutoConfigurationImportSelector 通过 SpringFactoriesLoader 从类门路上来读取 META-INF/spring.factories 文件信息,此文件中有一个 key 为 org.springframework.boot.autoconfigure.EnableAutoConfiguration,定义了一组须要主动配置的 bean。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\

这些配置类不是都会被加载,会依据 xxxAutoConfiguration 上的 @ConditionalOnClass 等条件判断是否加载,符合条件才会将相应的组件被加载到 spring 容器。(比方 mybatis-spring-boot-starter,会主动配置 sqlSessionFactory、sqlSessionTemplate、dataSource 等 mybatis 所需的组件)

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
        AnnotatedElement.class }) // 类门路存在 EnableAspectJAutoProxy 等类文件,才会加载此配置类
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = false)
    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
    public static class JdkDynamicAutoProxyConfiguration { }

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
    public static class CglibAutoProxyConfiguration {}}

全局配置文件中的属性如何失效,比方:server.port=8081,是如何失效的?

@ConfigurationProperties 的作用就是将配置文件的属性绑定到对应的 bean 上。全局配置的属性如:server.port 等,通过 @ConfigurationProperties 注解,绑定到对应的 XxxxProperties bean,通过这个 bean 获取相应的属性(serverProperties.getPort())。

//server.port = 8080
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
    private Integer port;
    private InetAddress address;

    @NestedConfigurationProperty
    private final ErrorProperties error = new ErrorProperties();
    private Boolean useForwardHeaders;
    private String serverHeader;
    //...
}

实现主动配置

实现当某个类存在时,主动配置这个类的 bean,并且能够在 application.properties 中配置 bean 的属性。

(1)新建 Maven 我的项目 spring-boot-starter-hello,批改 pom.xml 如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tyson</groupId>
    <artifactId>spring-boot-starter-hello</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>1.3.0.M1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
        </dependency>
    </dependencies>

</project>

(2)属性配置

public class HelloService {
    private String msg;

    public String getMsg() {return msg;}

    public void setMsg(String msg) {this.msg = msg;}

    public String sayHello() {return "hello" + msg;}
}


import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix="hello")
public class HelloServiceProperties {
    private static final String MSG = "world";
    private String msg = MSG;

    public String getMsg() {return msg;}

    public void setMsg(String msg) {this.msg = msg;}
}

(3)主动配置类

import com.tyson.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class) //1
@ConditionalOnClass(HelloService.class) //2
@ConditionalOnProperty(prefix="hello", value = "enabled", matchIfMissing = true) //3
public class HelloServiceAutoConfiguration {

    @Autowired
    private HelloServiceProperties helloServiceProperties;

    @Bean
    @ConditionalOnMissingBean(HelloService.class) //4
    public HelloService helloService() {HelloService helloService = new HelloService();
        helloService.setMsg(helloServiceProperties.getMsg());
        return helloService;
    }
}
  1. @EnableConfigurationProperties 注解开启属性注入,将带有 @ConfigurationProperties 注解的类注入为 Spring 容器的 Bean。
  2. 当 HelloService 在类门路的条件下。
  3. 当设置 hello=enabled 的状况下,如果没有设置则默认为 true,即条件合乎。
  4. 当容器没有这个 Bean 的时候。

(4)注册配置

想要主动配置失效,须要注册主动配置类。在 src/main/resources 下新建 META-INF/spring.factories。增加以下内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tyson.config.HelloServiceAutoConfiguration

“\” 是为了换行后依然能读到属性。若有多个主动配置,则用逗号隔开。

(5)应用 starter

在 Spring Boot 我的项目的 pom.xml 中增加:

<dependency>
    <groupId>com.tyson</groupId>
    <artifactId>spring-boot-starter-hello</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

运行类如下:

import com.tyson.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class SpringbootDemoApplication {

    @Autowired
    public HelloService helloService;

    @RequestMapping("/")
    public String index() {return helloService.getMsg();
    }

    public static void main(String[] args) {SpringApplication.run(SpringbootDemoApplication.class, args);
    }

}

在我的项目中没有配置 HelloService bean,然而咱们能够注入这个 bean,这是通过主动配置实现的。

在 application.properties 中增加 debug 属性,运行配置类,在控制台能够看到:

   HelloServiceAutoConfiguration matched:
      - @ConditionalOnClass found required class 'com.tyson.service.HelloService' (OnClassCondition)
      - @ConditionalOnProperty (hello.enabled) matched (OnPropertyCondition)

   HelloServiceAutoConfiguration#helloService matched:
      - @ConditionalOnMissingBean (types: com.tyson.service.HelloService; SearchStrategy: all) did not find any beans (OnBeanCondition)

能够在 application.properties 中配置 msg 的内容:

hello.msg= 大彬

@Value 注解的原理

@Value 的解析就是在 bean 初始化阶段。BeanPostProcessor 定义了 bean 初始化前后用户能够对 bean 进行操作的接口办法,它的一个重要实现类 AutowiredAnnotationBeanPostProcessor 为 bean 中的 @Autowired 和 @Value 注解的注入性能提供反对。

Spring Boot 须要独立的容器运行吗?

不须要,内置了 Tomcat/ Jetty 等容器。

Spring Boot 反对哪些日志框架?

Spring Boot 反对 Java Util Logging, Log4j2, Lockback 作为日志框架,如果你应用 Starters 启动器,Spring Boot 将应用 Logback 作为默认日志框架,然而不论是那种日志框架他都反对将配置文件输入到控制台或者文件中。

YAML 配置的劣势在哪里 ?

YAML 配置和传统的 properties 配置相比之下,有这些劣势:

  • 配置有序
  • 简洁明了,反对数组,数组中的元素能够是根本数据类型也能够是对象

毛病就是不反对 @PropertySource 注解导入自定义的 YAML 配置。

什么是 Spring Profiles?

在我的项目的开发中,有些配置文件在开发、测试或者生产等不同环境中可能是不同的,例如数据库连贯、redis 的配置等等。那咱们如何在不同环境中主动实现配置的切换呢?Spring 给咱们提供了 profiles 机制给咱们提供的就是来回切换配置文件的性能

Spring Profiles 容许用户依据配置文件(dev,test,prod 等)来注册 bean。因而,当应用程序在开发中运行时,只有某些 bean 能够加载,而在 PRODUCTION 中,某些其余 bean 能够加载。假如咱们的要求是 Swagger 文档仅实用于 QA 环境,并且禁用所有其余文档。这能够应用配置文件来实现。Spring Boot 使得应用配置文件非常简单。

SpringBoot 多数据源事务如何治理

第一种形式是在 service 层的 @TransactionManager 中应用 transactionManager 指定 DataSourceConfig 中配置的事务。

第二种是应用 jta-atomikos 实现分布式事务管理。

spring-boot-starter-parent 有什么用 ?

新创建一个 Spring Boot 我的项目,默认都是有 parent 的,这个 parent 就是 spring-boot-starter-parent,spring-boot-starter-parent 次要有如下作用:

  1. 定义了 Java 编译版本。
  2. 应用 UTF-8 格局编码。
  3. 执行打包操作的配置。
  4. 自动化的资源过滤。
  5. 自动化的插件配置。
  6. 针对 application.properties 和 application.yml 的资源过滤,包含通过 profile 定义的不同环境的配置文件,例如 application-dev.properties 和 application-dev.yml。

Spring Boot 打成的 jar 和一般的 jar 有什么区别 ?

  • Spring Boot 我的项目最终打包成的 jar 是可执行 jar,这种 jar 能够间接通过 java -jar xxx.jar 命令来运行,这种 jar 不能够作为一般的 jar 被其余我的项目依赖,即便依赖了也无奈应用其中的类。
  • Spring Boot 的 jar 无奈被其余我的项目依赖,次要还是他和一般 jar 的构造不同。一般的 jar 包,解压后间接就是包名,包里就是咱们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes 目录下才是咱们的代码,因而无奈被间接援用。如果非要援用,能够在 pom.xml 文件中减少配置,将 Spring Boot 我的项目打包成两个 jar,一个可执行,一个可援用。

SpringBoot 多数据源拆分的思路

先在 properties 配置文件中配置两个数据源,创立分包 mapper,应用 @ConfigurationProperties 读取 properties 中的配置,应用 @MapperScan 注册到对应的 mapper 包中。

正文完
 0