千家信息网

SpringBoot自动化配置的注解以及开关原理是怎样的

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章给大家介绍SpringBoot自动化配置的注解以及开关原理是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。FreeMarkerAutoConfiguration,这
千家信息网最后更新 2026年11月03日SpringBoot自动化配置的注解以及开关原理是怎样的

这篇文章给大家介绍SpringBoot自动化配置的注解以及开关原理是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

FreeMarkerAutoConfiguration,这个自动化配置类需要classloader中的一些类需要存在并且在其他的一些配置类之后进行加载。

SpringBoot的自动化配置原理

http://fangjian0423.github.io/2016/06/12/springboot-autoconfig-analysis/

但是还存在一些自动化配置类,它们需要在使用一些注解开关的情况下才会生效。比如spring-boot-starter-batch里的@EnableBatchProcessing注解、@EnableCaching等。

一个需求

在分析这些开关的原理之前,我们来看一个需求:

定义一个Annotation,让使用了这个Annotaion的应用程序自动化地注入一些类或者做一些底层的事情。

我们会使用Spring提供的@Import注解配合一个配置类来完成。

我们以一个最简单的例子来完成这个需求:定义一个注解EnableContentService,使用了这个注解的程序会自动注入ContentService这个bean。

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Import(ContentConfiguration.class)

public @interface EnableContentService {}

public interface ContentService {

void doSomething();

}

public class SimpleContentService implements ContentService {

@Override

public void doSomething() {

System.out.println("do some simple things");

}

}

然后在应用程序的入口加上@EnableContentService注解。

这样的话,ContentService就被注入进来了。 SpringBoot也就是用这个完成的。只不过它用了更加高级点的ImportSelector。

ImportSelector的使用

用了ImportSelector之后,我们可以在Annotation上添加一些属性,然后根据属性的不同加载不同的bean。

我们在@EnableContentService注解添加属性policy,同时Import一个Selector。

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Import(ContentImportSelector.class)

public @interface EnableContentService {

String policy() default "simple";

}

这个ContentImportSelector根据EnableContentService注解里的policy加载不同的bean。

public class ContentImportSelector implements ImportSelector {

@Override

public String[] selectImports(AnnotationMetadata importingClassMetadata) {

Class annotationType = EnableContentService.class;

AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(

annotationType.getName(), false));

String policy = attributes.getString("policy");

if ("core".equals(policy)) {

return new String[] { CoreContentConfiguration.class.getName() };

} else {

return new String[] { SimpleContentConfiguration.class.getName() };

}

}

}

CoreContentService和CoreContentConfiguration如下:

public class CoreContentService implements ContentService {

@Override

public void doSomething() {

System.out.println("do some import things");

}

}

public class CoreContentConfiguration {

@Bean

public ContentService contentService() {

return new CoreContentService();

}

}

这样的话,如果在@EnableContentService注解的policy中使用core的话,应用程序会自动加载CoreContentService,否则会加载SimpleContentService。

ImportSelector在SpringBoot中的使用

SpringBoot里的ImportSelector是通过SpringBoot提供的@EnableAutoConfiguration这个注解里完成的。

这个@EnableAutoConfiguration注解可以显式地调用,否则它会在@SpringBootApplication注解中隐式地被调用。

@EnableAutoConfiguration注解中使用EnableAutoConfigurationImportSelector作为ImportSelector。下面这段代码是EnableAutoConfigurationImportSelector中进行选择的具体代码:

@Override

public String[] selectImports(AnnotationMetadata metadata) {

try {

AnnotationAttributes attributes = getAttributes(metadata);

List configurations = getCandidateConfigurations(metadata,

attributes);

configurations = removeDuplicates(configurations); // 删除重复的配置

Set exclusions = getExclusions(metadata, attributes); // 去掉需要exclude的配置

configurations.removeAll(exclusions);

configurations = sort(configurations); // 排序

recordWithConditionEvaluationReport(configurations, exclusions);

return configurations.toArray(new String[configurations.size()]);

}

catch (IOException ex) {

throw new IllegalStateException(ex);

}

}

其中getCandidateConfigurations方法将获取配置类:

protected List getCandidateConfigurations(AnnotationMetadata metadata,

AnnotationAttributes attributes) {

return SpringFactoriesLoader.loadFactoryNames(

getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());

}

SpringFactoriesLoader.loadFactoryNames方法会根据FACTORIES_RESOURCE_LOCATION这个静态变量从所有的jar包中读取META-INF/spring.factories文件信息:

public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) {

String factoryClassName = factoryClass.getName();

try {

Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :

ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

List result = new ArrayList();

while (urls.hasMoreElements()) {

URL url = urls.nextElement();

Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));

String factoryClassNames = properties.getProperty(factoryClassName); // 只会过滤出key为factoryClassNames的值

result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));

}

return result;

}

catch (IOException ex) {

throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +

"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);

}

}

getCandidateConfigurations方法中的getSpringFactoriesLoaderFactoryClass方法返回的是EnableAutoConfiguration.class,所以会过滤出key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值。

下面这段配置代码就是autoconfigure这个jar包里的spring.factories文件的一部分内容(有个key为org.springframework.boot.autoconfigure.EnableAutoConfiguration,所以会得到这些AutoConfiguration):

# Initializers

org.springframework.context.ApplicationContextInitializer=\

org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

# Application Listeners

org.springframework.context.ApplicationListener=\

org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configure

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\

org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\

org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\

当然了,这些AutoConfiguration不是所有都会加载的,会根据AutoConfiguration上的@ConditionalOnClass等条件判断是否加载。

上面这个例子说的读取properties文件的时候只会过滤出key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值。

SpringBoot内部还有一些其他的key用于过滤得到需要加载的类:

  • org.springframework.test.context.TestExecutionListener

  • org.springframework.beans.BeanInfoFactory

  • org.springframework.context.ApplicationContextInitializer

  • org.springframework.context.ApplicationListener

  • org.springframework.boot.SpringApplicationRunListener

  • org.springframework.boot.env.EnvironmentPostProcessor

  • org.springframework.boot.env.PropertySourceLoader

关于SpringBoot自动化配置的注解以及开关原理是怎样的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

注解 配置 自动化 原理 方法 程序 不同 代码 内容 属性 应用程序 文件 需求 应用 这样的话 例子 更多 帮助 不错 高级 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技有限公司 南京欣网互联网络科技有限公司 重生之互联网科技帝国 涨乐互联网科技 互联网科技大会案例 互联网科技类展会 中正互联网科技招聘 中国最先进互联网科技公司 随着互联网科技发展 互联网科技创新服务 世界互联网领先科技成果获奖 黑科技 体验场景 互联网大会 启辰互联网科技 互联网领先科技宣传片 富国互联网金融科技混合基金 厦门江牛科技互联网 本届互联网大会上的黑科技 世界互联网科技成果奖 米泉互联网科技专业怎么样 互联网科技创业计划的风险分析 A股互联网金融科技公司 西藏七维空间互联网科技有限公司 广州优美互联网科技 崇明区互联网教育科技诚信经营 晓花互联网科技有限公司网址 互联网科技创新的路径 西安有哪些互联网高科技企业 科技互联网经济论坛 陕西彩京云互联网科技有限公司 互联网企业和网络科技有限公司
0