SpringBoot 自动装配-自定义Stater

3 阅读5分钟

自定义一个 SpringBoot Starter来验证自动装配的核心逻辑,从零开发一个「自定义日志 Starter」(命名为custom-log-starter),包含完整的代码、配置和验证步骤,验证自动装配的全过程。

一、核心思路(先明确自定义 Starter 的规范)

SpringBoot Starter 的核心是「约定大于配置」,自定义 Starter 需遵循以下规范:

  1. 命名规范:官方 Starter 命名为spring-boot-starter-xxx,自定义 Starter 建议命名为xxx-spring-boot-starter(比如custom-log-spring-boot-starter);

  2. 核心组成

    • 自动配置类(带条件注解的@Configuration类);
    • 配置属性类(@ConfigurationProperties,绑定 application.yml 配置);
    • 注册自动配置类(在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中声明);
  3. 验证逻辑:创建 Starter 后,在另一个 SpringBoot 项目中引入依赖,验证「自动装配生效、配置可自定义、条件注解可控」。

二、步骤 1:创建自定义 Starter 项目(Maven 工程)

1.1 项目结构

custom-log-spring-boot-starter/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── custom/
│   │   │           ├── config/
│   │   │           │   ├── CustomLogAutoConfiguration.java  // 自动配置类
│   │   │           │   └── CustomLogProperties.java         // 配置属性类
│   │   │           └── service/
│   │   │               └── CustomLogService.java            // 核心业务类
│   │   └── resources/
│   │       └── META-INF/
│   │           └── spring/
│   │               └── org.springframework.boot.autoconfigure.AutoConfiguration.imports  // 注册自动配置类
│   └── test/
└── pom.xml

1.2 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>

    <!-- 自定义Starter的GAV -->
    <groupId>com.custom</groupId>
    <artifactId>custom-log-spring-boot-starter</artifactId>
    <version>1.0.0</version>

    <!-- 父工程:SpringBoot 3.5 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.0</version>
        <relativePath/>
    </parent>

    <dependencies>
        <!-- SpringBoot自动配置核心依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- 配置属性绑定核心依赖(必须) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Lombok(可选,简化代码) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <!-- Maven编译配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>17</source> <!-- SpringBoot 3.5要求JDK 17+ -->
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

三、步骤 2:编写 Starter 核心代码

2.1 配置属性类(绑定 application.yml 配置)

作用:绑定配置文件中custom.log前缀的配置,支持自定义日志前缀、是否开启功能。

package com.custom.config;

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

/**
 * 自定义日志配置属性类
 */
@Data
@ConfigurationProperties(prefix = "custom.log") // 配置前缀:custom.log
public class CustomLogProperties {
    // 是否开启自定义日志(默认开启)
    private boolean enabled = true;
    // 日志前缀(默认值)
    private String prefix = "【自定义日志】";
}

2.2 核心业务类(自定义日志服务)

作用:提供自定义日志打印功能,作为 Starter 的核心功能载体。

package com.custom.service;

import lombok.AllArgsConstructor;
import com.custom.config.CustomLogProperties;

/**
 * 自定义日志服务类
 */
@AllArgsConstructor
public class CustomLogService {

    // 注入配置属性类
    private CustomLogProperties customLogProperties;

    /**
     * 自定义日志打印方法
     */
    public void printLog(String message) {
        if (customLogProperties.isEnabled()) {
            String log = customLogProperties.getPrefix() + message;
            System.out.println(log); // 简化实现,实际可集成logback/log4j
        }
    }
}

2.3 自动配置类(核心!控制自动装配逻辑)

作用:通过条件注解控制 Bean 的注册,体现自动装配的核心逻辑。

package com.custom.config;

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;
import com.custom.service.CustomLogService;

/**
 * 自定义日志自动配置类
 */
@Configuration // 标记为配置类
@ConditionalOnClass(CustomLogService.class) // 类路径有CustomLogService时生效(必选)
@EnableConfigurationProperties(CustomLogProperties.class) // 启用配置属性绑定
@ConditionalOnProperty(
    prefix = "custom.log",
    name = "enabled",
    havingValue = "true",
    matchIfMissing = true // 没配置时默认开启
)
public class CustomLogAutoConfiguration {

    /**
     * 注册CustomLogService Bean
     * @ConditionalOnMissingBean:用户自定义了该Bean则不注册(体现自定义覆盖默认)
     */
    @Bean
    @ConditionalOnMissingBean
    public CustomLogService customLogService(CustomLogProperties customLogProperties) {
        return new CustomLogService(customLogProperties);
    }
}

2.4 注册自动配置类(关键!让 SpringBoot 扫描到)

src/main/resources/META-INF/spring/目录下创建文件:org.springframework.boot.autoconfigure.AutoConfiguration.imports,内容为自动配置类的全限定名:

com.custom.config.CustomLogAutoConfiguration

四、步骤 3:打包 Starter 到本地仓库

执行 Maven 打包命令(确保本地有 Maven 环境,JDK 17+):

# 进入Starter项目根目录
cd custom-log-spring-boot-starter
# 打包并安装到本地Maven仓库
mvn clean install

执行成功后,本地仓库会出现com.custom:custom-log-spring-boot-starter:1.0.0依赖。

五、步骤 4:创建测试项目验证自动装配

创建一个新的 SpringBoot 3.5 项目(web 依赖即可),引入自定义 Starter,验证自动装配效果。

5.1 测试项目 pom.xml 引入 Starter

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 引入自定义Starter -->
    <dependency>
        <groupId>com.custom</groupId>
        <artifactId>custom-log-spring-boot-starter</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

5.2 编写测试代码

package com.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import com.custom.service.CustomLogService;

@SpringBootApplication
@RestController
public class TestApplication {

    // 自动注入Starter的CustomLogService(验证自动装配生效)
    @Resource
    private CustomLogService customLogService;

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

    @GetMapping("/testLog")
    public String testLog() {
        // 调用自定义日志方法
        customLogService.printLog("测试自动装配的自定义日志!");
        return "日志打印成功!";
    }
}

5.3 验证自动装配效果

验证 1:默认配置生效

直接启动测试项目,访问http://localhost:8080/testLog,控制台输出:

【自定义日志】测试自动装配的自定义日志!

说明:Starter 被自动装配,默认配置生效。

验证 2:自定义配置覆盖默认

在测试项目的application.yml中添加配置:

custom:
  log:
    prefix: "【自定义前缀-测试】" # 覆盖默认前缀
    enabled: true # 开启功能(默认true)

重启项目,访问接口,控制台输出:

【自定义前缀-测试】测试自动装配的自定义日志!

说明:配置属性绑定生效,自定义配置覆盖默认值。

验证 3:关闭功能(条件注解生效)

修改配置:

custom:
  log:
    enabled: false # 关闭自定义日志

重启项目,访问接口,控制台无输出,说明@ConditionalOnProperty条件注解生效,自动配置被关闭。

验证 4:自定义 Bean 覆盖自动装配

在测试项目中自定义CustomLogService Bean:

package com.test.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.custom.config.CustomLogProperties;
import com.custom.service.CustomLogService;

@Configuration
public class CustomConfig {

    // 自定义CustomLogService Bean
    @Bean
    public CustomLogService customLogService(CustomLogProperties customLogProperties) {
        return new CustomLogService(customLogProperties) {
            @Override
            public void printLog(String message) {
                System.out.println("【用户自定义Bean】" + message);
            }
        };
    }
}

重启项目,访问接口,控制台输出:

【用户自定义Bean】测试自动装配的自定义日志!

说明:@ConditionalOnMissingBean生效,用户自定义 Bean 覆盖了 Starter 的默认 Bean。

验证 5:debug 模式查看自动装配日志

启动测试项目时添加 JVM 参数-Ddebug,控制台会输出:

Positive matches:
-----------------
CustomLogAutoConfiguration matched:
  - @ConditionalOnClass found required class 'com.custom.service.CustomLogService' (OnClassCondition)
  - @ConditionalOnProperty (custom.log.enabled=true) matched (OnPropertyCondition)

清晰看到 CustomLogAutoConfiguration 的生效原因,验证了条件注解的作用。

总结

  1. 自定义 Starter 的核心步骤:编写配置属性类 → 编写自动配置类(带条件注解) → 注册自动配置类 → 打包 → 测试;
  2. 关键验证点:默认装配生效、配置属性绑定、条件注解控制、自定义 Bean 覆盖,完整验证了 SpringBoot 自动装配的核心逻辑;
  3. 核心原理:Starter 的自动配置类通过AutoConfiguration.imports被 SpringBoot 扫描,再通过条件注解按需注册 Bean,实现 “开箱即用、可配置、可覆盖”。

通过这个实战,你可以直观理解自动装配的所有核心知识点(条件注解、配置绑定、Bean 覆盖、SPI 加载),比单纯看理论更有说服力。