【Spring Boot 源码学习】@SpringBootApplication 注解

简介: 本篇介绍 @SpringBootApplication 注解的相关内容

微信图片_20231031101034.png

引言

在 Huazie 前面的博文 《Spring Boot 核心运行原理介绍》中,我们初步了解了 Spring Boot 核心运行原理,知道了 @EnableAutoConfiguration 是用来开启自动配置的注解。但创建过 Spring Boot 项目的读者肯定会说,我们并没有直接看到这个注解,实际上前面我也提到,它是由组合注解 @SpringBootApplication 引入的。

至于 @EnableAutoConfiguration 的讲解,我将放到后面再深入源码了解,本篇先介绍 组合注解 @SpringBootApplication

好了,废话不多说,看下面介绍:

主要内容

1. 创建 Spring Boot 项目

首先,我们打开 Intellij IDEA 开发工具,选择 File -> New -> Project

image.png

然后打开 New Project ,选择 Spring Initializr【这是用来创建 Spring Boot 项目】:

image.png

选择 Next,打开 Project Metadata【这里可以配置项目的一些基础信息】:

image.png

继续 Next,打开 Dependencies【有需要其他依赖可以添加】:

image.png

继续 Next,选择你的 Spring Boot 项目位置:

image.png

最后点 Finish 完成。

注意: 刚才新建的项目中,如果因为 Spring Boot 的版本问题导致项目报错,那就换个版本再试试。

2. Spring Boot 入口类

上述新建好的项目创建完成默认会生成一个 XXXApplication 的入口类。默认情况下,这个类的命名规则都是 artifactId + ApplicationartifactId 首字母大写】:

image.png

image.png

如上图中的 DemoApplication 就是我们这里 Spring Boot 项目的入口类,代码如下所示:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   

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

}

在上述的 Spring Boot 入口类 DemoApplication 中,唯一的注解就是 @SpringBootApplication。前面我们也提到了,它是通过其内部组合的 @EnableAutoConfiguration 来开启自动配置功能。

下面我们来详细介绍下 @SpringBootApplication 注解:

3. @SpringBootApplication 介绍

先来看 @SpringBootApplication 的源码【版本:2.7.9】:


@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 {
   

    /**
     * 排除特定的自动配置类,使它们永远不会被应用
     * @return 要排除(禁用)的类
     */
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class<?>[] exclude() default {
   };

    /**
     * 排除特定的自动配置类名称,以确保它们永远不会被应用
     * @return 要排除的自动配置类名称
     * @since 1.3.0
     */
    @AliasFor(annotation = EnableAutoConfiguration.class)
    String[] excludeName() default {
   };

    /**
     * 用于扫描带注解组件的基础包。使用 {@link #scanBasePackageClasses} 可以使用类型安全的方式替代基于字符串的包名。
     * <p>
     * 注意:该设置仅对 {@code @ComponentScan} 注解有效,不影响 {@code @Entity} 扫描或 Spring Data 的 {@link Repository} 扫描。
     * 对于这些情况,你应该添加 {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} 和
     * {@code @Enable...Repositories} 注解。
     * @return 要进行扫描的基础包
     * @since 1.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {
   };

    /**
     * 用于指定要扫描带注解组件的包的类型安全方式。将扫描指定类所在的包。
     * <p>
     * 考虑在每个包中创建一个特殊的空类或接口,只用于作为此属性引用的标记类。
     * <p>
     * 注意:该设置仅对 {@code @ComponentScan} 注解有效,不影响 {@code @Entity} 扫描或 Spring Data 的 {@link Repository} 扫描。
     * 对于这些情况,你应该添加 {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} 和
     * {@code @Enable...Repositories} 注解。
     * @return 要进行扫描的基础包
     * @since 1.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {
   };

    /**
     * 用于在 Spring 容器中为检测到的组件命名的 {@link BeanNameGenerator} 类。
     * <p>
     * {@link BeanNameGenerator} 接口本身的默认值表示应该使用处理此 {@code @SpringBootApplication} 注解的扫描器的继承的 bean 名称生成器,
     * 例如默认的 {@link AnnotationBeanNameGenerator} 或在引导时提供给应用程序上下文的任何自定义实例。
     * @return 要使用的 {@link BeanNameGenerator}
     * @see SpringApplication#setBeanNameGenerator(BeanNameGenerator)
     * @since 2.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    /**
     * 指定是否应代理 {@link Bean @Bean} 方法以强制执行 bean 的生命周期行为,例如,即使在用户代码中直接调用 {@code @Bean} 方法,
     * 也能返回共享的单例 bean 实例。此功能需要方法拦截,通过运行时生成的 CGLIB 子类来实现,其中包括一些限制,例如配置类及其方法不允许声明为 {@code final}。
     * <p>
     * 默认值为 {@code true},允许在配置类内部进行 'inter-bean references',同时允许从另一个配置类中调用此配置的 {@code @Bean} 方法。
     * 如果每个特定配置的 {@code @Bean} 方法都是自包含的并且设计为容器使用的普通工厂方法,则可以将此标志切换为 {@code false},
     * 以避免 CGLIB 子类处理。
     * <p>
     * 关闭 bean 方法拦截将实际上像在非 {@code @Configuration} 类上声明的那样单独处理 {@code @Bean} 方法,也就是 "@Bean Lite Mode"
     * (参见 {@link Bean @Bean 的文档})。因此,在行为上等同于删除 {@code @Configuration} 注解。
     * @since 2.2
     * @return 是否代理 {@code @Bean} 方法
     */
    @AliasFor(annotation = Configuration.class)
    boolean proxyBeanMethods() default true;

}

通过查看上述源码,我们可以看到 @SpringBootApplication 注解提供如下的成员属性【这里默认大家都是知道 注解中的成员变量是以方法的形式存在的】:

  • exclude :根据类(Class)排除指定的自动配置,该成员属性覆盖了 @SpringBootApplication 中组合的 @EnableAutoConfiguration 中定义的 exclude 成员属性。
  • excludeName :根据类名排除指定的自动配置,覆盖了 @EnableAutoConfiguration 中定义的 excludeName 成员属性。
  • scanBasePackages :指定扫描的基础 package,用于扫描带注解组件的基础包,例如包含 @Component 等注解的组件。
  • scanBasePackageClasses :指定扫描的类,用于相关组件的初始化。
  • nameGenerator :用于在 Spring 容器中为检测到的组件命名的 BeanNameGenerator 类。
  • proxyBeanMethods :指定是否代码 @Bean 方法以强制执行 bean 的生命周期行为。该功能需要通过运行时生成 CGLIB 子类来实现方法拦截。不过它包括一定的限制,例如配置类及其方法不允许声明为 final 等。proxyBeanMethods 的默认值为 true,允许配置类中进行 inter-bean references(bean 之间的引用)以及对该配置的 @Bean 方法的外部调用。如果 @Bean 方法都是自包含的,并且仅提供了容器使用的普通工程方法的功能,则可设置为 false,避免处理 CGLIB 子类。另外我们从源码中 @since 2.2 处也可以看出来,该属性是在 Spring Boot 2.2 版本新增的。

细心的读者,可能看过上面的源码会发现,@SpringBootApplication 注解的成员属性上大量使用了 @AliasFor 注解,那该注解有什么作用呢?

@AliasFor 注解用于桥接其他注解,它的 annotation 属性中指定了所桥接的注解类。如果我们点到 annotation 属性配置的注解中,可以看出 @SpringBootApplication 注解的成员属性其实已经在其他注解中定义过了。那之所以使用 @AliasFor 注解并重新在 @SpringBootApplication 中定义,主要就是为了减少用户在使用多注解上的麻烦。

知识拓展:
简单总结一下 @AliasFor 的作用:

  • 定义别名关系:通过在注解属性上使用 @AliasFor 注解,可以将一个属性与另一个属性建立别名关系。这意味着当使用注解时,你可以使用别名属性来设置目标属性的值。
  • 属性互通:通过在两个属性上使用 @AliasFor 注解,并且将它们的 attribute 属性分别设置为对方,可以实现属性之间的双向关联。这意味着当设置其中一个属性的值时,另一个属性也会自动被赋予相同的值。
  • 注解继承:当一个注解 A 使用 @AliasFor 注解指定了另一个注解 B 的属性为自己的别名属性时,如果类使用了注解 A,那么注解 B 的相关属性也会得到相应的设置。

Spring Boot 早期的版本中并没有 @SpringBootConfiguration 注解,它是后面的版本新加的,其内组合了 @Configuration 注解,如下图所示:

image.png

@EnableAutoConfiguration 注解组合了 @AutoConfigurationPackage 注解,如下图所示:

image.png

除了一些元注解和基础注解,我们用一张类图来描述下 @SpringBootApplication 注解的组合结构:

image.png

从上图中,我们可以总结一下 @SpringBootApplication 注解的核心作用,如下:

  • 组合 @EnableAutoConfiguration,用于开启 Spring Boot 的自动配置功能;
  • 组合 @ComponentScan,用于激活 @Component 等注解类的初始化;
  • 组合 @SpringBootConfiguration,用于标识一个类为配置类,以便在 Spring 应用程序上下文中进行配置。

总结

本篇通过查看 @SpringBootApplication 注解的源码,介绍其成员属性和组合注解的相关内容,这些内容将为我们后续的源码学习打下基础。下一篇博文,我们将开始介绍 @EnableAutoConfiguration 注解,开启 Spring Boot 的自动配置功能,敬请期待!!!

目录
相关文章
|
6月前
|
监控 Java 应用服务中间件
微服务——SpringBoot使用归纳——为什么学习Spring Boot
本文主要探讨为什么学习Spring Boot。从Spring官方定位来看,Spring Boot旨在快速启动和运行项目,简化配置与编码。其优点包括:1) 良好的基因,继承了Spring框架的优点;2) 简化编码,通过starter依赖减少手动配置;3) 简化配置,采用Java Config方式替代繁琐的XML配置;4) 简化部署,内嵌Tomcat支持一键式启动;5) 简化监控,提供运行期性能参数获取功能。此外,从未来发展趋势看,微服务架构逐渐成为主流,而Spring Boot作为官方推荐技术,与Spring Cloud配合使用,将成为未来发展的重要方向。
192 0
微服务——SpringBoot使用归纳——为什么学习Spring Boot
|
28天前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
5月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
375 70
|
3月前
|
Java 测试技术 数据库
说一说 SpringBoot 整合 Junit5 常用注解
我是小假 期待与你的下一次相遇 ~
|
5月前
|
Java Spring
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
143 20
|
5月前
|
人工智能 缓存 自然语言处理
保姆级Spring AI 注解式开发教程,你肯定想不到还能这么玩!
这是一份详尽的 Spring AI 注解式开发教程,涵盖从环境配置到高级功能的全流程。Spring AI 是 Spring 框架中的一个模块,支持 NLP、CV 等 AI 任务。通过注解(如自定义 `@AiPrompt`)与 AOP 切面技术,简化了 AI 服务集成,实现业务逻辑与 AI 基础设施解耦。教程包含创建项目、配置文件、流式响应处理、缓存优化及多任务并行执行等内容,助你快速构建高效、可维护的 AI 应用。
|
6月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
493 0
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
229 1
|
11月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
416 5