千家信息网

Java中复合注解@SpringBootApplication怎么使用

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,本篇内容介绍了"Java中复合注解@SpringBootApplication怎么使用"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!
千家信息网最后更新 2026年11月04日Java中复合注解@SpringBootApplication怎么使用

本篇内容介绍了"Java中复合注解@SpringBootApplication怎么使用"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

对SpringBoot工程的自动配置很感兴趣,于是学习其源码并整理了其中一些内容,如果有错误请大家指正~话不多说,直接上源码;

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

可以看到这是一个复合注解,一共包括7个不同的注解,下面对这7个不同的注解进行分析。

注解

注解1:@Target({ElementType.TYPE})

用来表示注解作用范围,TYPE表示作用范围为类或接口。

注解2:@Retention(RetentionPolicy.RUNTIME)

注解3:@Documented

表明这个注释是由 javadoc记录的。

注解4:@Inherited

放在注解上,当父类加了@SpringBootApplication注解时,子类也会继承这个注解(对接口的实现类无效)。

注解5:@SpringBootConfiguration

底层仍是@Configuration注解, 源码如下:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @interface SpringBootConfiguration {}
注解6:@ComponetScan

@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。

可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。

注解:@EnableAutoConfiguration

个人感觉@EnableAutoConfiguration这个Annotation最为重要它的作用可以概括为:借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器。

其源码如下:

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

这里需要关注@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)两个注解。

注释:@AutoConfigurationPackage

源码如下:

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

可以发现这个注解的核心其实也是Import注解,表示对于标注该注解的类的包,应当使用AutoConfigurationPackages注册。接着看Registrar这个类:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {    @Override      //metadata是我们注解所在的元信息    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {            //将我们注解所在包下所有的组件进行注册      register(registry, new PackageImport(metadata).getPackageName());    }    @Override    public Set determineImports(AnnotationMetadata metadata) {      return Collections.singleton(new PackageImport(metadata));    }}

这个类中的核心方法是register方法:

private static final String BEAN = AutoConfigurationPackages.class.getName();    public static void register(BeanDefinitionRegistry registry, String... packageNames) {    if (registry.containsBeanDefinition(BEAN)) {      BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);      ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();      constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));    }    else {      GenericBeanDefinition beanDefinition = new GenericBeanDefinition();      beanDefinition.setBeanClass(BasePackages.class);      beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);      beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);      registry.registerBeanDefinition(BEAN, beanDefinition);    }}

register方法的逻辑非常清晰:如果这个bean已经被注册,就获取它的构造函数参数值,并将包名添加进去;否则就创建一个新的bean定义并进行注册。通过@AutoConfigurationPackage这个注解,可以将注解所在包下所有的组件进行注册。

注解:@Import(AutoConfigurationImportSelector.class)

这个注解导入了AutoConfigurationImportSelector这个类这个类的核心方法是selectImports方法,实现ImportSelector接口。方法基于我们在pom.xml文件中配置的jar包和组件进行导入。所以方法返回的是一个Class全路径的String数组,返回的Class会被Spring容器管理。方法源码如下:

@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {  if (!isEnabled(annotationMetadata)) {    return NO_IMPORTS;  }  AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader      .loadMetadata(this.beanClassLoader);  AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,      annotationMetadata);  return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}

这个方法的结构也很清晰,首先通过isEnabled方法判断是否需要进行导入,如果需要导入的话,通过loadMetadata方法获取配置信息,并通过getAutoConfigurationEntry进行自动装配。isEnabled方法源码如下:

protected boolean isEnabled(AnnotationMetadata metadata) {  if (getClass() == AutoConfigurationImportSelector.class) {    return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);  }  return true;}

这个方法通过EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY这个配置项进行判断是否需要自动配置,默认为true。loadMetadata方法源码如下:

protected static final String PATH = "META-INF/" + "spring-autoconfigure-metadata.properties";  public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {    return loadMetadata(classLoader, PATH);  }  static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {    try {      Enumeration urls = (classLoader != null) ? classLoader.getResources(path)          : ClassLoader.getSystemResources(path);      Properties properties = new Properties();      while (urls.hasMoreElements()) {        properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));      }      return loadMetadata(properties);    }    catch (IOException ex) {      throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);    }  }  static AutoConfigurationMetadata loadMetadata(Properties properties) {    return new PropertiesAutoConfigurationMetadata(properties);  }

可以看到这个方法会加载META-INF/spring-autoconfigure-metadata.properties下的所有配置信息并包装成AutoConfigurationMetadata对象返回。

注:spring-autoconfigure-metadata.properties文件在spring-boot-autoconfigure-2.1.9.RELEASE.jar/META-INF下。

getAutoConfigurationEntry方法源码如下:

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,      AnnotationMetadata annotationMetadata) {    if (!isEnabled(annotationMetadata)) {      return EMPTY_ENTRY;    }    AnnotationAttributes attributes = getAttributes(annotationMetadata);    List configurations = getCandidateConfigurations(annotationMetadata, attributes);    configurations = removeDuplicates(configurations);    Set exclusions = getExclusions(annotationMetadata, attributes);    checkExcludedClasses(configurations, exclusions);    configurations.removeAll(exclusions);    configurations = filter(configurations, autoConfigurationMetadata);    fireAutoConfigurationImportEvents(configurations, exclusions);    return new AutoConfigurationEntry(configurations, exclusions);}

这个方法是AutoConfiguration的主流程方法,可以将这个方法的每一行看做一个步骤,那么处理步骤如下:

1. 加载配置了@EnableAutoConfiguration注解的属性值getAttribute方法:

protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {    String name = getAnnotationClass().getName();    AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));    Assert.notNull(attributes, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()        + " annotated with " + ClassUtils.getShortName(name) + "?");    return attributes;}

2.得到META-INF/spring.factories文件中以@EnableAutoConfiguration完全限定类名做key的value,getCandidateConfigurations方法:

protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {    List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),        getBeanClassLoader());    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "        + "are using a custom packaging, make sure that file is correct.");    return configurations;}protected Class getSpringFactoriesLoaderFactoryClass() {    return EnableAutoConfiguration.class;}

其中,SpringFactoriesLoader.loadFactoryNames()这个方法的作用是使用给定的类加载器从META-INF/spring.factories加载给定类型的工厂实现的完全限定类名;

3.去重;

4.得到需要排除的类的类名,这些类可以在@EnableAutoConfiguration注解中配置;

5.检查这两个集合;

6.把需要排除的类移除;

7.根据OnBeanCondition、OnClassCondition等条件进行过滤(有兴趣可以深入了解);

8.广播事件,得到AutoConfigurationImportListener所有实现类,然后生成事件进行广播;

9.把需要装配和排除的类完全限定名封装成了AutoConfigurationEntry对象返回。

因此,@EnableAutoConfiguration可以简单总结为:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中EnableAutoConfiguration对应的配置项通过反射实例化为对应的标注了@Configuration的IoC容器配置类,并加载到IoC容器。

"Java中复合注解@SpringBootApplication怎么使用"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

注解 方法 配置 源码 容器 作用 所在 文件 组件 信息 内容 条件 核心 类名 范围 不同 重要 两个 事件 兴趣 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网加科技 江苏根荣互联网科技 上海互联网科技有限公司 北京互联网科技公司 时间互联网络科技 滨湖区互联网智能科技产品供应 哈尔滨新华互联网科技学院 中国科技互联网公司收入 欧洲十大科技互联网公司 金融科技与互联网金融相同和不同 中国航天科技大学国际工业互联网 华中科技大学互联网的牛人 城市宝互联网科技有限公司 广州百诚互联网科技有限公司官网 美国互联网科技公司 互联网领先科技活动 互联网科技博主张洲 上海旺乐尼互联网科技有限公司 广东猫王互联网科技有限公司电话 东风日产互联网科技公司叫什么 互联网 科技公司 亿策互联网科技 长亮科技互联网金融 互联网科技英文翻译 滨湖区互联网智能科技产品供应 中国科技互联网公司收入 互联网还是高科技吗 迪庆互联网科技招生 四川互联网展示科技馆设计 广州有谷有贝互联网科技有限公司
0