当前位置: 首页 > article >正文

Spring Boot 应用开发中的核心注解及扩展(包含自动配置源码追踪)

前言:

本文将带大家深入了解 Spring Boot 开发中的核心注解及其扩展功能。同时,文末附有自动配置相关的源码追踪与解析,对这一机制感兴趣的读者可以参考。

1.核心注解

1. @SpringBootApplication

@SpringBootApplication 是 Spring Boot 应用的入口注解,它是以下三个注解的组合:

  • @EnableAutoConfiguration:启用自动配置。
  • @ComponentScan:扫描当前包及其子包中的组件。
  • @Configuration:标记为配置类,等同于传统的 XML 配置文件。
作用

作为 Spring Boot 应用的启动类,加载配置,扫描组件,初始化上下文。

示例
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

2. @EnableAutoConfiguration

@EnableAutoConfiguration 是 Spring Boot 自动配置的核心注解,用于根据类路径中的依赖和配置文件动态配置 Spring Bean。

工作原理
  1. 条件装配(Condition-based Configuration)

    • 使用 @ConditionalOnClass, @ConditionalOnMissingBean 等注解判断是否加载某些配置。
    • 示例:当类路径中检测到 spring-webmvc 时,将自动配置 Spring MVC 的相关组件。
  2. 配置文件驱动

    • 自动读取

      application.properties
      

      application.yml
      

      中的属性调整行为:

      server.port=8081  # 设置服务器端口
      spring.datasource.url=jdbc:mysql://localhost:3306/mydb
      
  3. 自动配置类清单

    • 配置类清单位于

      META-INF/spring.factories
      

      文件中,列出了所有可用的自动配置类。

      org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
      org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
      
  4. 排除某些配置

    • 可以通过

      exclude
      

      排除不需要的自动配置:

      @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
      

3. @ComponentScan

@ComponentScan 用于扫描指定包及其子包中的组件,并注册到 Spring 容器中。

属性
  • basePackages:指定需要扫描的包。
  • basePackageClasses:指定类所在的包作为扫描路径。
示例
@SpringBootApplication
@ComponentScan(basePackages = {"com.example.service", "com.example.repository"})
public class MyApplication {
}

4. @Configuration

@Configuration 注解标记一个类为配置类,它可以用来定义 Bean。

示例
@Configuration
public class MyConfig {
    @Bean
    public MyService myService() {
        return new MyService();
    }
}

5. @Conditional 系列注解

Spring Boot 通过一组条件注解实现了智能化配置:

  • @ConditionalOnClass:当指定的类存在时生效。
  • @ConditionalOnMissingBean:当容器中缺少指定 Bean 时生效。
  • @ConditionalOnProperty:当某个配置属性满足条件时生效。
  • @ConditionalOnExpression:基于 SpEL 表达式条件加载。
示例
@Configuration
@ConditionalOnClass(name = "com.example.MyClass")
public class MyConditionalConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

6. @RestController

@RestController@Controller@ResponseBody 的组合注解,简化了返回 JSON 数据的开发。

示例
@RestController
public class MyController {
    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, Spring Boot!";
    }
}

7. @ConfigurationProperties

@ConfigurationProperties 用于将配置文件中的属性绑定到一个类中。

示例
@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private String name;
    private String version;
    // getters and setters
}
绑定配置
app.name=MyApp
app.version=1.0

8. @SpringBootTest

@SpringBootTest 用于测试 Spring Boot 应用,加载完整的应用上下文。

示例
@SpringBootTest
public class MyApplicationTests {
    @Test
    void contextLoads() {
    }
}

9. @EnableConfigurationProperties

配合 @ConfigurationProperties 使用,用于启用基于配置的属性绑定。

示例
@EnableConfigurationProperties(AppConfig.class)
public class MyApplication {
}

2. 配合 Starter 模块扩展功能

Spring Boot 的自动配置能力与 Starter 模块密切相关。
Starter,是一系列预定义的依赖集合,简化了应用开发 。

常见 Starter

  • spring-boot-starter-web:用于开发 Web 应用。
  • spring-boot-starter-data-jpa:用于与数据库交互。
  • spring-boot-starter-security:用于集成 Spring Security。

使用示例

只需引入相关 Starter Spring Boot 就会自动配置所需的 Bean:

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

3. 结合 SpringApplication 的高级功能

SpringApplication 类提供了许多功能,可以结合 @SpringBootApplication 实现丰富的启动配置。

自定义启动行为

  1. 设置启动参数 可以通过 SpringApplication 的方法自定义启动配置:

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MyApplication.class);
        app.setAdditionalProfiles("dev"); // 启用 dev 配置
        app.run(args);
    }
    
  2. 事件和监听器

    • Spring Boot 提供了一系列启动事件(如 ApplicationStartingEventApplicationReadyEvent

    • 可以通过实现

      ApplicationListener
      

      接口监听这些事件:

      @Component
      public class MyAppListener implements ApplicationListener<ApplicationReadyEvent> {
          @Override
          public void onApplicationEvent(ApplicationReadyEvent event) {
              System.out.println("Application is ready!");
          }
      }
      

4. 与 Spring Cloud 的集成

当项目使用 Spring Cloud 时 @SpringBootApplication 会与云服务的功能无缝集成,例如配置中心、服务注册与发现。

示例:注册到 Eureka

引入依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

添加注解:

@SpringBootApplication
@EnableEurekaClient // 注册为 Eureka 客户端
public class CloudApplication {
}

5. 主类的多种使用方式

@SpringBootApplication 的标注类通常是应用的主类,但可以扩展其功能以满足更复杂的需求。

嵌套上下文

当需要在一个应用中使用多个 Spring 上下文时,可以通过子上下文(SpringApplicationBuilder)实现:

public static void main(String[] args) {
    new SpringApplicationBuilder(ParentApplication.class)
        .child(ChildApplication.class)
        .run(args);
}

条件化主类

通过条件注解决定是否加载某些主类:

@SpringBootApplication
@ConditionalOnProperty(name = "feature.enabled"  havingValue = "true")
public class FeatureApplication {
}

6. 最佳实践

  1. 主类应放在根包中
    • 这样可以覆盖整个项目的扫描路径,避免遗漏。
  2. 精简自动配置
    • 使用 spring.autoconfigure.excludeexclude 属性排除不需要的配置,提升性能。
  3. 分层配置
    • 使用 application.yml 文件结合 @ConfigurationProperties 管理复杂配置。
  4. 开发与生产分离
    • 使用 spring.profiles.active 激活不同的环境配置。

7.自动配置源码追踪

  1. Spring Boot 自动配置源码解析与优化总结

    Spring Boot 的自动配置机制是其核心功能之一,通过一系列注解和类实现了智能化配置加载 大大简化了开发工作,以下是对其核心注解、源码实现及优化的详细解析和总结:


    1. @SpringBootApplication

    @SpringBootApplication 是 Spring Boot 的入口注解,它本质上是一个组合注解,包含以下部分:

    • @SpringBootConfiguration:标记当前类为 Spring Boot 配置类 相当于传统 Spring 的 @Configuration
    • @ComponentScan:开启组件扫描 默认扫描该类所在包及其子包中的所有组件。
    • @EnableAutoConfiguration:负责自动加载符合条件的配置类。
    源码片段
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(
        excludeFilters = {
            @Filter(type = FilterType.CUSTOM  classes = {TypeExcludeFilter.class}) 
            @Filter(type = FilterType.CUSTOM  classes = {AutoConfigurationExcludeFilter.class})
        }
    )
    public @interface SpringBootApplication {
        // 省略部分代码
    }
    

    2. @EnableAutoConfiguration

    @EnableAutoConfiguration 是实现自动配置的关键注解,它通过 @Import 导入了 AutoConfigurationImportSelector 类,用于筛选、加载自动配置类。

    源码片段
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
        Class<?>[] exclude() default {}; // 排除特定的自动配置类
        String[] excludeName() default {}; // 按名称排除
    }
    

    3. 自动配置类的加载逻辑

    AutoConfigurationImportSelector@EnableAutoConfiguration 中的核心实现类,负责加载所有自动配置类 。

    关键方法:getAutoConfigurationEntry
    • 条件校验:调用 isEnabled 方法判断是否启用自动配置。
    • 获取候选配置类: 使用 getCandidateConfigurationsMETA-INF/spring.factories 文件中加载配置类。
    • 去重与排除
      • 去除重复配置类:removeDuplicates
      • 排除不需要的类:getExclusions
    • 过滤与事件触发
      • 通过 ConfigurationClassFilter 对配置类进行过滤。
      • 触发自动配置事件:fireAutoConfigurationImportEvents
    源码片段
    /**
     * 根据提供的注解元数据获取自动配置条目。
     * 该方法用于判断自动配置是否启用,处理配置项,应用过滤和排除规则,并生成最终的 AutoConfigurationEntry。
     *
     * @param annotationMetadata 注解元数据信息。
     * @return 包含配置项和排除项的 AutoConfigurationEntry。
     */
    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        // 判断是否启用自动配置,如果未启用,则返回空的配置条目。
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY; // 如果自动配置被禁用,直接返回空条目。
        }
        
        // 获取注解的属性信息。
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        
        // 根据注解元数据和属性获取候选的配置类列表。
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        
        // 去除配置列表中的重复项。
        configurations = this.removeDuplicates(configurations);
        
        // 获取需要排除的配置类集合。
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        
        // 检查排除的类是否与候选配置类冲突。
        this.checkExcludedClasses(configurations, exclusions);
        
        // 从候选配置列表中移除排除的类。
        configurations.removeAll(exclusions);
        
        // 通过配置类过滤器进一步筛选配置类。
        configurations = this.getConfigurationClassFilter().filter(configurations);
        
        // 触发自动配置导入事件,通知相关监听器。
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        
        // 返回包含最终配置类和排除类的自动配置条目。
        return new AutoConfigurationEntry(configurations, exclusions);
    }
    
    

    4. 自动配置文件解析

    Spring Boot 的自动配置类在 META-INF/spring.factories 文件中定义 getCandidateConfigurations 方法会从该文件中读取所有配置类的全限定名,并加载到 Spring 容器。

    spring.factories 示例
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration \
    org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
    
    • EnableAutoConfiguration:列出了所有可能的自动配置类。
    • 这些类会在运行时动态加载,并根据条件注解(如 @ConditionalOnClass)决定是否生效。

    5. 属性绑定与配置
    • 全局配置类:使用 @ConfigurationProperties 注解的类,用于绑定配置文件中的属性。
    • 绑定逻辑
      1. 从配置文件(application.ymlapplication.properties)中读取属性。
      2. 使用 Binder 机制将属性值注入到配置类中。
    示例
    @ConfigurationProperties(prefix = "spring.datasource")
    public class DataSourceProperties {
        private String url;
        private String username;
        private String password;
        // getters and setters
    }
    
    配置文件
    spring.datasource.url=jdbc:mysql://localhost:3306/mydb
    spring.datasource.username=root
    spring.datasource.password=root
    

    6. 优化与扩展
    1. 排除不需要的自动配置

      • 如果某些自动配置类不符合需求,可以通过:

        exclude
        

        将属性排除:

        @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
        
    2. 按需加载配置

      • 使用 @ConditionalOnClass@ConditionalOnProperty 等条件注解,实现按需加载。

      • 示例:

        @Configuration
        @ConditionalOnProperty(name = "feature.enabled"  havingValue = "true")
        public class FeatureConfig {
            // 配置逻辑
        }
        
    3. 自定义自动配置

      • 创建自定义配置类,并在

        spring.factories
        

        中注册:

        @Configuration
        public class MyAutoConfiguration {
            @Bean
            public MyService myService() {
                return new MyService();
            }
        }
        
    4. 调试自动配置

      • 使用 spring-boot-starter-actuator 提供的 /actuator/conditions 端点,可以查看哪些配置类生效或被排除。

    7. 总结

    Spring Boot 自动配置通过核心注解(如 @EnableAutoConfiguration)、配置文件(spring.factories)、条件化注解(@Conditional 系列)等机制实现了模块化和智能化配置,开发者可以通过排除、不加载、添加自定义配置等方式进行优化和扩展 从而构建更高效和灵活的应用程序。


http://www.kler.cn/a/504868.html

相关文章:

  • 计算机二级-Java系列(Java的特点)
  • Python线性混合效应回归LMER分析大鼠幼崽体重数据、假设检验可视化|数据分享...
  • 最左前缀匹配原则
  • Vue 3前端与Python(Django)后端接口简单示例
  • 手撕代码: C++实现按位序列化和反序列化
  • Wireshark 使用教程:网络分析从入门到精通
  • 2025.1.15——二、字符型注入
  • STM32 物联网智能家居 (三) 输入子系统
  • 语言月赛 202407【significance】题解(AC)
  • Web_HTML+CSS_First_Asignment
  • C#对动态加载的DLL进行依赖注入,并对DLL注入服务
  • 前端组件开发:组件开发 / 定义配置 / 配置驱动开发 / 爬虫配置 / 组件V2.0 / form表单 / table表单
  • linux 端口转发工具rinetd
  • Flask安全开发
  • 亚洲科技创新之夜即将闪耀CES Asia 2025首日
  • 网络安全测评质量管理与标准解读
  • Tmux复制时将内容传递到系统剪贴板
  • vue2 web 多标签输入框 elinput是否当前焦点
  • C++ 数据结构:基本概念、时间复杂度、空间复杂度
  • YOLOv9改进,YOLOv9自研检测头融合HAttention用于图像修复的混合注意力检测头
  • Leetcode 474. 一和零 多重背包问题,动态规划
  • QT 键值对集合QMap
  • 【WEB】网络传输中的信息安全 - 加密、签名、数字证书与HTTPS
  • 标准通上线标准「全文检索」功能,提升查询精准度!
  • Android控件底色蓝色无法修改、高版本无法安装app、找不到xml、找不到java文件、目录不显示等问题
  • windows下编译php源码