Spring Boot 核心注解全解:@SpringBootApplication背后的三剑客

大家好呀!👋 今天我们要聊一个超级重要的Spring Boot话题 - 那个神奇的主类注解@SpringBootApplication!很多小伙伴可能每天都在用Spring Boot开发项目,但你真的了解这个注解背后的秘密吗?🤔

别担心,今天我就用最通俗易懂的方式,带大家彻底搞懂这个"三合一"的超级注解!保证连小学生都能听懂!🎯 文章会很长很详细,但绝对值得你花时间看完!💪

一、先来认识下主角:@SpringBootApplication

每次我们创建一个Spring Boot项目,都会在主类上看到这个注解:

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

看起来很简单对吧?但你知道吗,这个注解其实是个"三合一"的超级注解!🦸‍♂️ 它由三个核心注解组合而成:

  1. @SpringBootConfiguration - 配置担当
  2. @EnableAutoConfiguration - 自动装配担当
  3. @ComponentScan - 组件扫描担当

接下来我们就一个个拆解,看看它们各自有什么本领!🔍

二、第一剑客:@SpringBootConfiguration

1. 基本介绍

@SpringBootConfiguration是Spring Boot特有的配置注解,它实际上是@Configuration注解的"加强版"💪。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}

从代码可以看出,它本质上就是一个@Configuration,但加上了Spring Boot的特殊标识。

2. 它能做什么?

  • 标识配置类:告诉Spring"这是一个配置类,里面有Bean的定义哦!"📝
  • 定义Bean:可以在类里用@Bean注解定义各种组件
  • 替代XML配置:以前用XML配置的Bean,现在可以用Java代码来配置了

3. 实际使用示例

@SpringBootConfiguration
public class MyConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}@Beanpublic DataSource dataSource() {// 配置数据源return new HikariDataSource();}
}

4. 与@Configuration的区别

虽然功能相同,但@SpringBootConfiguration有特殊含义:

  • 它通常只用于主配置类(就是有main方法的那个类)
  • Spring Boot在内部处理时会特殊对待它
  • 一般项目中建议还是用@Configuration,除非是主类

5. 小测验

❓ 问题:如果一个类被@SpringBootConfiguration标注,Spring会怎么处理它?
💡 答案:Spring会把它当作配置类处理,扫描其中的@Bean方法,并将返回的对象注册为Spring容器中的Bean。

三、第二剑客:@EnableAutoConfiguration

这是三个剑客中最强大也最神奇的一个!✨ 它开启了Spring Boot的"自动装配"魔法!

1. 自动装配是什么?

想象你去吃自助餐🍽️:

  • 传统Spring:你需要自己点每道菜(手动配置每个Bean)
  • Spring Boot:看到你走进来,就自动把你可能喜欢的菜都端上来了(自动配置)

这就是自动装配的魅力!它根据你添加的依赖,自动配置Spring应用。

2. 工作原理揭秘

@EnableAutoConfiguration背后的魔法是这样实现的:

  1. 读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件:这个文件里列出了所有自动配置类
  2. 条件过滤:根据当前环境(类路径、已有Bean等)过滤掉不适用的配置
  3. 应用配置:将符合条件的配置类加载进来

3. 自动配置示例

举个例子🌰:

  • 你在pom.xml中添加了spring-boot-starter-data-jpa
  • Spring Boot看到后:“哦!你需要JPA支持!”
  • 自动配置数据源、EntityManager等JPA相关Bean

4. 查看自动配置报告

想知道哪些自动配置生效了?可以这样查看:

在application.properties中添加:

debug=true

启动时会打印类似这样的报告:

=========================
AUTO-CONFIGURATION REPORT
=========================Positive matches:
-----------------DataSourceAutoConfiguration matched:- @ConditionalOnClass found org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType (OnClassCondition)Negative matches:
-----------------ActiveMQAutoConfiguration:Did not match:- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

5. 自定义自动配置

你也可以创建自己的自动配置!步骤:

  1. 创建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
  2. 写入你的配置类全限定名
  3. 使用@Conditional系列注解控制条件

6. 排除自动配置

如果不想要某些自动配置,可以排除它们:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApplication {// ...
}

或者在配置文件中:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

7. 小测验

❓ 问题:为什么我们加了spring-boot-starter-web依赖后,Tomcat就自动启动了?
💡 答案:因为@EnableAutoConfiguration检测到类路径下有Servlet相关的类,自动加载了Tomcat的配置。

四、第三剑客:@ComponentScan

1. 组件扫描是什么?

@ComponentScan就像Spring的"雷达"📡,它会扫描指定包及其子包下的组件(被@Component@Service@Repository等注解的类),并把它们注册为Spring Bean。

2. 默认行为

@SpringBootApplication中,如果没有指定扫描路径:

  • 默认扫描主类所在包及其子包
  • 这也是为什么我们通常把主类放在项目最外层包

3. 自定义扫描路径

如果你想扫描其他包,可以这样:

@SpringBootApplication
@ComponentScan({"com.myapp", "com.shared"})
public class MyApplication {// ...
}

4. 过滤组件

你可以包含或排除特定组件:

@ComponentScan(basePackages = "com.myapp",excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.myapp.test.*")
)

5. 与XML配置的对比

以前在XML中是这样配置组件扫描的:


现在用注解更加简洁方便!

6. 实际应用技巧

  • 组织包结构:合理组织包结构,让扫描更高效
  • 避免全盘扫描:不要扫描不必要的包(如第三方jar包)
  • 多模块项目:在多模块项目中,注意主类的位置

7. 小测验

❓ 问题:如果把主类放在com.myapp包,但你的Service类在com.service包,会发生什么?
💡 答案:Service类不会被自动扫描到,需要手动添加@ComponentScan("com.service")或者把Service移到com.myapp或其子包下。

五、三剑客如何协同工作

现在我们已经认识了三位剑客,来看看它们是如何配合的:🤝

  1. 启动阶段:SpringApplication.run()启动时
  2. @SpringBootConfiguration:先识别这是一个配置类
  3. @ComponentScan:扫描组件,注册Bean定义
  4. @EnableAutoConfiguration:根据条件自动配置
  5. Bean实例化:所有Bean定义就绪后,实例化Bean

它们的执行顺序非常重要!组件扫描要先于自动配置,这样自动配置才能基于已有Bean进行条件判断。

六、深入理解:@SpringBootApplication源码解析

让我们看看这个注解的庐山真面目:

@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 {// 可以指定排除的自动配置类@AliasFor(annotation = EnableAutoConfiguration.class)Class[] exclude() default {};// 可以指定排除的自动配置类名@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};// 可以自定义扫描包@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")String[] scanBasePackages() default {};// 可以自定义扫描类@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")Class[] scanBasePackageClasses() default {};
}

可以看到,它主要是组合了三个注解,并提供了一些便捷的属性来配置它们。

七、实际开发中的最佳实践

1. 主类位置

✅ 正确做法:放在项目最顶层包

com
└── myapp├── Application.java  ← 主类在这里├── controller├── service└── repository

❌ 错误做法:放在深层包中

com
└── myapp├── config│   └── Application.java  ← 主类放太深了!├── controller├── service└── repository

2. 多模块项目配置

对于多模块项目,可以这样组织:

// 主模块中的主类
@SpringBootApplication
@ComponentScan({"com.myapp.module1","com.myapp.module2","com.myapp.shared"
})
public class MyApplication {// ...
}

3. 自定义配置技巧

  • 排除特定自动配置:如测试时排除安全配置
  • 精细控制扫描:只扫描必要的包提高性能
  • 组合使用:可以同时使用这三个注解进行更细粒度控制

八、常见问题解答

Q1: 为什么我的自定义配置类不生效?

可能原因:

  1. 没有放在组件扫描的路径下
  2. 类上没有加@Configuration或相关注解
  3. 被其他配置覆盖了

解决方案:

  • 检查包结构
  • 添加@Configuration
  • 使用@Order调整顺序

Q2: 自动配置太魔法了,如何知道发生了什么?

解决方法:

  1. 开启debug模式(debug=true
  2. 查看/actuator/conditions端点(需要actuator依赖)
  3. 阅读官方文档的自动配置部分

Q3: 如何覆盖自动配置的Bean?

很简单,只需要自己定义一个同类型的Bean:

@Bean
public DataSource dataSource() {// 你的自定义数据源return new MyCustomDataSource();
}

Spring Boot会优先使用你的Bean而不是自动配置的。

九、高级话题:自定义@SpringBootApplication

你甚至可以创建自己的"增强版"@SpringBootApplication

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableCaching
@EnableAsync
public @interface MyEnhancedSpringBootApplication {// 可以添加自定义属性
}

然后就可以这样使用:

@MyEnhancedSpringBootApplication
public class MyApplication {// ...
}

这样就把缓存和异步支持也默认集成了!

十、总结回顾

今天我们深入剖析了@SpringBootApplication背后的三位剑客:

  1. @SpringBootConfiguration - 标识这是一个配置类
  2. @EnableAutoConfiguration - 开启自动配置魔法
  3. @ComponentScan - 自动扫描组件

记住它们的协作关系:

  • 先识别配置
  • 再扫描组件
  • 最后自动配置

理解这些核心注解的工作原理,能让你更好地掌握Spring Boot,并在遇到问题时快速定位原因!💡

希望这篇长文对你有所帮助!如果有任何问题,欢迎留言讨论~ 😊

Happy Coding! 🚀

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/76799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

weibo_har鸿蒙微博分享,单例二次封装,鸿蒙微博,微博登录

weibo_har鸿蒙微博分享,单例二次封装,鸿蒙微博 HarmonyOS 5.0.3 Beta2 SDK,原样包含OpenHarmony SDK Ohos_sdk_public 5.0.3.131 (API Version 15 Beta2) 🏆简介 zyl/weibo_har是微博封装使用,支持原生core使用 &a…

tomcat集成redis实现共享session

中间件&#xff1a;Tomcat、Redis、Nginx jar包要和tomcat相匹配 jar包&#xff1a;commons-pool2-2.2.jar、jedis-2.5.2.jar、tomcat-redis-session-manage-tomcat7.jar 配置Tomcat /conf/context.xml <?xml version1.0 encodingutf-8?> <!--Licensed to the A…

JavaScript 扩展Array类方法实现数组求和

题目描述&#xff1a;使用原型对象扩展Array类&#xff0c;实现返回数字型数组的和 <script>const arr [1,2,3,4,5,6]Array.prototype.sum function(){return this.reduce((prev,item)>prev item,0)}console.log(arr.sum())</script>求和函数中this 指向调用…

中间件--ClickHouse-11--部署示例(Linux宿主机部署,Docker容器部署)

一、Linux宿主机部署 1、环境准备 操作系统&#xff1a;推荐使用 CentOS 7/8 或 Ubuntu 18.04/20.04。硬件要求&#xff1a; 至少 2 核 CPU 和 4GB 内存。足够的磁盘空间&#xff08;根据数据量评估&#xff09;。CPU需支持SSE4.2指令集&#xff08;可通过以下命令检查&#…

鸿蒙NEXT开发权限工具类(申请授权相关)(ArkTs)

import abilityAccessCtrl, { Permissions } from ohos.abilityAccessCtrl; import { bundleManager, common, PermissionRequestResult } from kit.AbilityKit; import { BusinessError } from ohos.base; import { ToastUtil } from ./ToastUtil;/*** 权限工具类&#xff08;…

LVGL学习(二)(lv_label,lv_btn)

3-1_标签(lv_label) 一、标签的组成&#xff08;盒子模型&#xff09;​​ 标签由三个核心模块构成&#xff0c;类似便签纸的​​分层设计​​&#xff1a; ​​LV_PART_MAIN&#xff08;主体层&#xff09;​​ ​​功能​​&#xff1a;相当于便签纸的"纸面"&…

深度剖析神经网络:从基础原理到面试要点(二)

引言 在人工智能蓬勃发展的今天&#xff0c;神经网络作为其核心技术之一&#xff0c;广泛应用于图像识别、自然语言处理、语音识别等众多领域。深入理解神经网络的数学模型和结构&#xff0c;对于掌握人工智能技术至关重要。本文将对神经网络的关键知识点进行详细解析&#xf…

【java+Mysql】学生信息管理系统

学生信息管理系统是一种用于管理学生信息的软件系统&#xff0c;旨在提高学校管理效率和服务质量。本课程设计报告旨在介绍设计和实现学生信息管理系统的过程。报告首先分析了系统的需求&#xff0c;包括学生基本信息管理、成绩管理等功能。接着介绍了系统的设计方案&#xff0…

Linux mmp文件映射补充(自用)

addr一般为NULL由OS指明&#xff0c;length所需长度&#xff08;4kb对齐&#xff09;&#xff0c;prot&#xff08;权限&#xff0c;一般O_RDWR以读写&#xff09;&#xff0c; flag&#xff08;MAP_SHARED(不刷新到磁盘上&#xff0c;此进程独有)和MAP_PRIVATE&#xff08;刷新…

Nginx openresty web服务 与 Go 原生web服务性能对比

1 概述 Nginx采用的是IO复用模型&#xff0c;能处理超高并发。 Go语言采用协程&#xff0c;能轻量级的处理超高并发。 那么在不考虑业务逻辑复杂的前提下&#xff0c;即假如将Nginx和Go都提供一个/test接口&#xff0c;并在接口逻辑中都只是让其做20毫秒的耗时操作&#xff0c…

[创业之路-377]:企业法务 - 有限责任公司与股份有限公司的优缺点对比

有限责任公司&#xff08;简称“有限公司”&#xff09;与股份有限公司&#xff08;简称“股份公司”&#xff09;是我国《公司法》规定的两种主要公司形式&#xff0c;二者在设立条件、治理结构、股东权利义务等方面存在显著差异。以下从核心特征、设立条件、治理结构、股东权…

QEMU源码全解析 —— 块设备虚拟化(21)

接前一篇文章:QEMU源码全解析 —— 块设备虚拟化(20) 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM源码解析与应用》 —— 李强,机械工业出版社 特此致谢! 上一回开始解析blockdev_init函数,讲到了其中调用的blk_new_open函数,该函数的作用…

蓝桥杯中的知识点

总结&#xff1a; 这次考的并不理想 比赛前好多知识点遗漏 但到此为止已经结束了 mod 是 模运算&#xff08;Modulo Operation&#xff09;的缩写&#xff0c;表示求两个数相除后的 余数 10mod31 (a % b) &#xff08;7%21&#xff09; 1e9代表1乘以10的9次方&#xff0c…

批量替换多个 Word 文档中的指定图片

在 Word 文档中&#xff0c;我们可以插入各种各样的图片&#xff0c;比如插入 logo、插入设计图、施工图等等。在某些情况下&#xff0c;我们也会碰到需要将 Word 文档中某张图片替换成其它图片的场景&#xff0c;比如将旧的 Logo 替换成新的 Logo。当我们有大量的 Word 文档需…

基于微信小程序的中医小妙招系统的设计与实现

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生…

Java 8 新特性深度解析:现代编程的转折点

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Java 8 是 Java 发展史上的重要里程碑&#xff0c;它引入了函数式编程范式、增强了集合处理能力&#xff0c;并彻底革新了日期时间处理方式。本文将通过代码示…

鹧鸪云平台实时追踪任务进度的核心机制

一、‌三维可视化监控‌ BIMGIS融合建模‌&#xff1a;通过无人机测绘与三维建模技术生成施工场地数字孪生模型&#xff0c;支持实时查看各标段三维模型与施工进度的匹配度&#xff0c;偏差超过5%自动触发预警。 进度匹配度分析‌&#xff1a;中央数据中台整合施工规划、资源…

【Spring Boot】MyBatis多表查询的操作:注解和XML实现SQL语句

1.准备工作 1.1创建数据库 &#xff08;1&#xff09;创建数据库&#xff1a; CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;&#xff08;2&#xff09;使用数据库 -- 使⽤数据数据 USE mybatis_test;1.2 创建用户表和实体类 创建用户表 -- 创建表[⽤⼾表…

ISO15189认证有什么要求?ISO15189认证流程

ISO 15189 认证要求及流程详解 ISO 15189 是国际标准化组织&#xff08;ISO&#xff09;针对 医学实验室质量和能力 的认证标准&#xff0c;适用于医院检验科、第三方医学实验室、血站等机构。该认证确保实验室的技术能力和管理体系符合国际标准&#xff0c;提高检测结果的准确…

【Linux】调试工具gdb的认识和使用指令介绍(图文详解)

目录 1、debug和release的知识 2、gdb的使用和常用指令介绍&#xff1a; &#xff08;1&#xff09;、windows下调试的功能&#xff1a; &#xff08;2&#xff09;、进入和退出&#xff1a; &#xff08;3&#xff09;、调试过程中的相关指令&#xff1a; 3、调试究竟是在…