Skip to content

05-SpringBoot 高级 ​

对应原始资料:springBoot高级、SpringBoot高级原理-部署.md

一、自动配置原理(核心) ​

1. @SpringBootApplication ​

java
@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan

2. @EnableAutoConfiguration ​

  • 用 @Import(AutoConfigurationImportSelector.class) 导入一堆自动配置类。
  • 加载 META-INF/spring.factories(SpringBoot 2.x)/ META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(3.x)。
  • 每个自动配置类(如 DataSourceAutoConfiguration)带 @Conditional 条件注解,满足条件才生效。

3. 常用条件注解 ​

注解含义
@ConditionalOnClassclasspath 有指定类才生效
@ConditionalOnMissingBean容器中没有指定 Bean 才生效
@ConditionalOnBean有指定 Bean 才生效
@ConditionalOnProperty配置项满足条件才生效
@ConditionalOnWebApplication是 Web 应用才生效

4. 一句话原理 ​

SpringBoot 启动时加载所有自动配置类(xxxAutoConfiguration),每个配置类根据条件决定是否生效;一旦生效就用 @Bean 向容器注册组件,组件需要的参数从 xxxProperties 类(绑定 yml)读取。

5. 案例:DataSourceAutoConfiguration ​

  1. 引入 mysql-connector、druid。
  2. 容器中没有 DataSource → 自动配置 HikariCP/Druid。
  3. 参数从 DataSourceProperties 读取,绑定 yml 的 spring.datasource.*。
  4. 你可以自定义一个 DataSource Bean,覆盖默认(@ConditionalOnMissingBean)。

二、自定义 Starter ​

1. 为什么自定义 Starter ​

团队内封装通用组件(如统一认证、限流、监控),做成 starter 让其他项目一行依赖即可用。

2. 步骤 ​

① 创建普通模块,依赖 spring-boot-autoconfigure。

② 写配置类:

java
@ConfigurationProperties(prefix = "hello")
@Data
public class HelloProperties {
    private String name;
    private String prefix;
}

@Configuration
@EnableConfigurationProperties(HelloProperties.class)
@ConditionalOnProperty(prefix = "hello", name = "enabled", havingValue = "true")
public class HelloAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public HelloService helloService(HelloProperties p) {
        return new HelloService(p);
    }
}

③ 注册自动配置:resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

com.itheima.hello.HelloAutoConfiguration

④ 使用方依赖该 starter,在 yml 配置即可触发。

三、Profile 多环境 ​

yaml
spring:
  profiles:
    active: dev      # 激活 dev

文档块方式(单文件):

yaml
spring:
  profiles: dev
server:
  port: 8080
---
spring:
  profiles: prod
server:
  port: 80

四、配置优先级(高 → 低) ​

  1. 命令行参数 --server.port=9090。
  2. JNDI / 环境变量。
  3. jar 同目录的 application.yml。
  4. jar 内的 application-{profile}.yml。
  5. jar 内的 application.yml。

五、内嵌容器 ​

  • 默认 Tomcat。
  • 换 Jetty / Undertow:排除 tomcat starter,引入对应 starter。
  • 调优:server.tomcat.threads.max=200 等。

六、Actuator 生产监控 ​

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

访问:

  • /actuator/health:健康检查。
  • /actuator/beans:所有 Bean。
  • /actuator/metrics:指标。
  • 暴露所有:management.endpoints.web.exposure.include=*。

七、整合第三方(常用) ​

1. Redis ​

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
yaml
spring:
  redis:
    host: localhost
    port: 6379
java
@Autowired private StringRedisTemplate redis;
redis.opsForValue().set("k", "v");
String v = redis.opsForValue().get("k");

2. Quartz / XXL-Job 定时任务 ​

SpringBoot 原生定时:

java
@EnableScheduling
@SpringBootApplication
public class App { }

@Component
public class Task {
    @Scheduled(cron = "0 0 2 * * ?")     // 每天凌晨 2 点
    public void run() { }
}

3. Swagger / Knife4j(接口文档) ​

xml
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>...</version>
</dependency>

访问 /doc.html。

八、部署 ​

1. 打 jar ​

mvn clean package → java -jar app.jar。

2. 后台运行(Linux) ​

bash
nohup java -jar app.jar --spring.profiles.active=prod > app.log 2>&1 &

3. Docker 部署(见 06 模块) ​

dockerfile
FROM openjdk:8-jdk
COPY app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

4. 分层 jar / 增量构建 ​

SpringBoot 默认分层(dependencies / application),配合 Docker 多阶段构建加速。

九、性能与最佳实践 ​

  • 关闭 devtools 在生产。
  • 用 HikariCP 连接池(默认)。
  • 日志用 logback async + 滚动。
  • JVM 参数:-Xms -Xmx -XX:+UseG1GC。
  • 用 Lombok / MapStruct 减少模板代码。

练习建议 ​

  1. 调试启动过程,打印自动配置报告 --debug,看哪些生效哪些不生效。
  2. 自定义一个 starter(如 hello-spring-boot-starter)。
  3. 整合 actuator,访问 /actuator/health。
  4. 用 @Scheduled 写一个每天清理日志的任务。
  5. 用 Docker 部署你的 SpringBoot 项目。