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-connectordruid
  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 packagejava -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 项目。