Spring Boot 二次开发详解:从自定义 Starter 到框架扩展

Spring Boot 二次开发详解:从自定义 Starter 到框架扩展

# Spring Boot 二次开发详解:从自定义 Starter 到框架扩展

## 一、Spring Boot 简介与二次开发价值

Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。

### 二次开发的核心价值

– **统一规范**:在企业中建立统一的开发标准和最佳实践
– **简化流程**:封装常用功能,降低开发复杂度
– **快速复用**:通过 Starter 快速复用已验证的功能模块
– **集中管理**:统一管理依赖版本、配置项和组件初始化

### 适用场景

1. 企业级框架定制
2. 内部组件封装
3. 通用功能模块化
4. 技术栈标准化

## 二、自定义 Starter 开发

### 1. Starter 的结构

一个标准的 Starter 包含以下部分:

“`
my-spring-starter
├── src/main/java
│ └── com.example
│ ├── MyAutoConfiguration.java
│ ├── MyProperties.java
│ └── MyStarterApplication.java
├── src/main/resources
│ └── META-INF
│ └── spring.factories
└── pom.xml
“`

### 2. Spring.factories 配置

“`properties
# src/main/resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
“`

### 3. 自动配置类

“`java
@Configuration
@ConditionalOnClass(MyService.class)
@ConditionalOnMissingBean(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {

@Bean
@ConfigurationProperties(prefix = “my”)
public MyProperties myProperties() {
return new MyProperties();
}

@Bean
public MyService myService(MyProperties properties) {
return new MyService(properties);
}

@Bean
@ConditionalOnProperty(prefix = “my”, name = “enabled”, havingValue = “true”)
public MyController myController(MyService service) {
return new MyController(service);
}
}
“`

## 三、Auto Configuration 原理

### 1. 自动配置加载流程

“`java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
// @SpringBootApplication 包含 @EnableAutoConfiguration
SpringApplication.run(Application.class, args);
}
}
“`

### 2. 核心注解解析

“`java
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_ATTR = “spring.boot.enableautoconfiguration”;

@AliasFor(annotation = ImportSelector.class)
String[] exclude() default {};

@AliasFor(annotation = ImportSelector.class)
String[] excludeName() default {};
}
“`

### 3. 条件注解详解

“`java
// 1. 类存在条件
@ConditionalOnClass(String.class)

// 2. 类不存在条件
@ConditionalOnMissingClass(“com.example.NotFoundClass”)

// 3. Bean 存在条件
@ConditionalOnBean(MyService.class)

// 4. Bean 不存在条件
@ConditionalOnMissingBean(MyService.class)

// 5. 属性条件
@ConditionalOnProperty(prefix = “my”, name = “enabled”)

// 6. 资源条件
@ConditionalOnResource(resources = “classpath:config.properties”)

// 7. 表达式条件
@ConditionalOnExpression(“${my.enabled:false} == true”)
“`

## 四、自定义 Starter 实战

### 1. 完整 Starter 示例

“`java
// MyProperties.java
@ConfigurationProperties(prefix = “my-starter”)
public class MyProperties {

private boolean enabled = true;
private String apiKey;
private int timeout = 3000;

// Getters and Setters
}
“`

“`java
// MyAutoConfiguration.java
@Configuration
@ConditionalOnProperty(name = “my-starter.enabled”)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {

@Autowired
private MyProperties properties;

@Bean
public MyApiClient myApiClient() {
return new MyApiClient(properties.getApiKey(), properties.getTimeout());
}

@Bean
@ConditionalOnMissingBean
public MyService myService(MyApiClient client) {
return new MyService(client);
}
}
“`

“`java
// MyApiClient.java
public class MyApiClient {

private final String apiKey;
private final int timeout;

public MyApiClient(String apiKey, int timeout) {
this.apiKey = apiKey;
this.timeout = timeout;
}

public String fetchData(String url) {
// 实现 HTTP 请求逻辑
return “data”;
}
}
“`

“`java
// MyService.java
@Service
public class MyService {

private final MyApiClient apiClient;

public MyService(MyApiClient apiClient) {
this.apiClient = apiClient;
}

public String getData() {
return apiClient.fetchData(“https://api.example.com/data”);
}
}
“`

“`java
// MyController.java
@RestController
@RequestMapping(“/my”)
public class MyController {

private final MyService myService;

public MyController(MyService myService) {
this.myService = myService;
}

@GetMapping(“/data”)
public String getData() {
return myService.getData();
}
}
“`

### 2. 使用场景

“`yaml
# application.yml
my-starter:
enabled: true
api-key: your-api-key
timeout: 5000
“`

## 五、扩展 Spring Boot Actuator

### 1. 自定义健康检查

“`java
@Component
public class CustomHealthIndicator implements HealthIndicator {

@Autowired
private MyService myService;

@Override
public Health health() {
try {
// 检查服务状态
String result = myService.getData();

if (result != null && !result.isEmpty()) {
return Health.up()
.withDetail(“service”, “healthy”)
.withDetail(“lastCheck”, System.currentTimeMillis())
.build();
}

return Health.down()
.withDetail(“service”, “no data”)
.build();

} catch (Exception e) {
return Health.down(e)
.withDetail(“error”, e.getMessage())
.build();
}
}
}
“`

### 2. 自定义 Endpoint

“`java
@RestController
@RequestMapping(“/custom”)
public class CustomEndpoint extends AbstractDelegatingExposableEndpoint> {

private final MyService myService;

public CustomEndpoint(MyService myService) {
super(“custom”);
this.myService = myService;
}

@Override
protected Map invoke() {
Map result = new HashMap<>();
result.put(“status”, “running”);
result.put(“service”, myService.getData());
result.put(“timestamp”, System.currentTimeMillis());
return result;
}
}
“`

### 3. 自定义 Metric

“`java
@Component
public class CustomMetrics {

private final MeterRegistry meterRegistry;

public CustomMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;

// 注册自定义指标
Counter counter = Counter.builder(“my.service.calls”)
.description(“My service call count”)
.register(meterRegistry);

meterRegistry.gauge(“my.service.latency”,
() -> myService.getLatency());
}

public void recordCall() {
meterRegistry.counter(“my.service.calls”).increment();
}
}
“`

## 六、CLI 工具开发

### 1. Spring Boot CLI 应用

“`groovy
// MyTool.groovy
#!/usr/bin/env groovy

@Grab(‘org.springframework.boot:spring-boot-starter:3.1.0’)
@Grab(‘com.fasterxml.jackson.core:jackson-databind:2.15.0’)

import groovy.json.JsonSlurper

class MyTool {

static void main(String[] args) {
def tool = new MyTool()
tool.run(args)
}

def run(String[] args) {
switch(args[0]) {
case ‘generate’:
generateConfig(args[1])
break
case ‘validate’:
validateConfig(args[1])
break
default:
println ‘Usage: mytool [args]’
}
}

def generateConfig(String output) {
def config = [
appName: ‘My Application’,
version: ‘1.0.0’,
environment: ‘development’,
settings: [
timeout: 3000,
retries: 3
]
]

def writer = new FileWriter(output)
def json = new JsonOutput().toJson(config)
writer.write(json)
writer.close()

println “Config generated: $output”
}

def validateConfig(String input) {
def reader = new FileReader(input)
def json = new JsonSlurper().parseText(reader.text)

if (!json.appName || !json.version) {
throw new IllegalArgumentException(‘Invalid config’)
}

println ‘Config is valid’
}
}
“`

### 2. 打包可执行 CLI

“`xml

org.codehaus.gmavenplus
gmavenplus-plugin
3.0.0



execute


org.springframework.boot
spring-boot-maven-plugin

“`

## 七、模板引擎定制

### 1. 自定义 Thymeleaf 处理器

“`java
@Configuration
public class CustomThymeleafConfig implements WebMvcConfigurer {

@Autowired
private ApplicationContext applicationContext;

@Bean
public SpringViewResolver viewResolver() {
SpringViewResolver resolver = new SpringViewResolver();
resolver.setViewResolvers(applicationContext.getBeanFactory()
.getBeansOfType(ViewResolver.class).values());
return resolver;
}
}
“`

### 2. 自定义 Thymeleaf 表达式

“`java
@Component
public class CustomExpressionObjectFactory implements ExpressionObjectFactory {

private final CustomTemplateHelper helper;

public CustomExpressionObjectFactory(CustomTemplateHelper helper) {
this.helper = helper;
}

@Override
public ExpressionObject createExpressionObject(SpringContext context) {
return new CustomExpressionObject(context, helper);
}
}
“`

### 3. 自定义模板引擎

“`java
@Component
public class CustomTemplateEngine {

private final TemplateEngine templateEngine;

public CustomTemplateEngine() {
this.templateEngine = new SpringTemplateEngine();

// 添加方言
templateEngine.setDialect(new SpringStandardDialect());

// 添加处理器
templateEngine.addTemplateResolver(new ClassLoaderTemplateResolver());
templateEngine.addTemplateResolver(new ServletContextTemplateResolver());
}

public String process(String templateName, Context context) {
return templateEngine.process(templateName, context);
}
}
“`

## 八、最佳实践与注意事项

### 1. Starter 开发最佳实践

“`java
// ✅ 正确:使用条件注解
@Configuration
@ConditionalOnClass(Service.class)
@ConditionalOnMissingBean(Service.class)
public class MyAutoConfiguration {
@Bean
public Service service() {
return new Service();
}
}

// ❌ 错误:无条件注册 Bean
@Configuration
public class MyAutoConfiguration {
@Bean
public Service service() {
return new Service(); // 可能覆盖用户配置
}
}
“`

### 2. 配置属性管理

“`java
// ✅ 正确:使用@ConfigurationProperties
@ConfigurationProperties(prefix = “my”)
public class MyProperties {
private String name;
private int timeout = 3000;
}

// ❌ 错误:硬编码配置
public class MyService {
private static final String API_KEY = “xxx”;
}
“`

### 3. 依赖管理

“`xml


org.springframework.boot
spring-boot-autoconfigure
provided



com.example
some-lib
1.0.0

“`

### 4. 测试策略

“`java
@SpringBootTest(classes = MyAutoConfiguration.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
public class MyAutoConfigurationTest {

@Autowired
private MyService myService;

@Test
public void testService() {
assertNotNull(myService);
}
}
“`

### 5. 版本兼容性

“`java
// ✅ 正确:使用版本导入



org.springframework.boot
spring-boot-dependencies
3.1.0
pom
import



“`

## 总结

Spring Boot 二次开发能够极大提升开发效率和代码质量。通过自定义 Starter,可以封装通用功能,建立企业级开发标准。

**核心要点回顾:**
– ✅ 理解 Auto Configuration 原理
– ✅ 掌握自定义 Starter 开发
– ✅ 扩展 Actuator 功能
– ✅ 开发 CLI 工具
– ✅ 遵循最佳实践

#SpringBoot #Java #二次开发 #微服务 #框架定制 #自动化配置

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
相关推荐
  • 暂无相关文章
  • 评论 抢沙发

    请登录后发表评论

      暂无评论内容