SpringBootApplication注解解析

@SpringBootApplication是SpringBoot的核心注解,由@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan组成。@SpringBootConfiguration是@Configuration的别名,用于配置类。@EnableAutoConfiguration启动自动配置,借助@Import导入AutoConfigurationImportSelector选择自动配置类。@AutoConfigurationPackage处理启动类所在包的扫描。@ComponentScan扫描指定包下的组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

本文主要用于记录自己学习SpringBoot源码过程中的收获,不一定准确,仅供参考。

SpringBootApplication注解简介

@SpringBootApplication注解是一个复合注解,主要是由 @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan三个注解组合而成。

SpringBootConfiguration注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

从源码可以看出,该注解主要是引用 @Configuration 注解,将其作为配置类注入。

EnableAutoConfiguration注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

同样从源码可以看出,该注解主要是由两部分来实现,其一是通过 @Import 注解引入 AutoConfigurationImportSelector 类,其二是引入注解 @AutoConfigurationPackage

AutoConfigurationImportSelector

这一部分内容主要是自动导入的一些原理,简要来说,该类实现了 ImportSelector 接口,在项目启动的过程中,会自动调用其 selectImports方法,选择出需要自动导入的类,其过程比较重要,详细分析过程可以见博客~(SpringBoot自动注入分析)。

AutoConfigurationPackage

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

该注解主要是通过 @Import 注解引入 Registrar 类,该类是 AutoConfigurationPackages
的静态内部类,核心方法如下:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {			
		register(registry, new PackageImport(metadata).getPackageName());
	}

	@Override
	public Set<Object> determineImports(AnnotationMetadata metadata) {
		return Collections.singleton(new PackageImport(metadata));
	}
}

其实 Registrar 的作用没有想象中的那么难以理解,因为我们想要导入类,一个一个使用 import 的话就很慢,这里 registerBeanDefinitions 方法其实就是批量注册。
AnnotationMetadata 这个代表的是注解元数据,怎么理解呢,其实就是我们当前所注解类的信息。在这里的话其实就代表 AutoConfigurationPackage 注解标在了哪、它的每一个属性值都是什
么,通过打断点可以看到这里的 metadata 所代表的的信息如下:

这里的class显示的是主程序启动类的信息,因为我们注解是依次往下分析的,最初的注解还是 @SpringBootApplication,所以标记的类为启动类。

register(registry, new PackageImport(metadata).getPackageName());

registerBeanDefinitions 方法主要还是调用的 register 方法,入参除了 registry 之外,还有新建了一个对象为 PackageImport 。它也是 AutoConfigurationPackages 类的静态内部类,入参是我们的 metadata, 最终获取到包名,给予 register 方法的入参也包名,也就是我们启动类的包名,相当于把我们整个包里面的内容都要做注册操作。这里我们也可以理解,为什么我们要把启动类放到包的最外层。

ComponentScan注解

ComponentScan 做的事情就是告诉Spring从哪里找到bean,可以指定去扫描那些包、排除那些包,这里默认就会扫描我们main方法所在的包及其下级包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值