spring.factories 与 注解的联合使用案例

在阅读spring-boot相关源码时,常常见到spring.factories文件,里面写了自动配置(AutoConfiguration)相关的类名,因此产生了一个疑问:“明明自动配置的类已经打上了@Configuration的注解,为什么还要写spring.factories文件?”

这个话题需要从@SpringBootApplication注解开始说起。

查看@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 {
	……
}

其中比较重要的是@EnableAutoConfiguration和@ComponentScan两个注解。@ComponentScan注解的作用是扫描@SpringBootApplication所在的Application类(即spring-boot项目的入口类)所在的包(basepackage)下所有的@component注解(或拓展了@component的注解)标记的bean,并注册到spring容器中。

看到这里也许会有个疑问,在spring-boot项目中pom文件里面添加的依赖中的bean(spring-boot项目外的bean)是如何注册到spring-boot项目的spring容器中的呢?

这就需要讨论@EnableAutoConfiguration的作用。查看@EnableAutoConfiguration源码,

@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(AutoConfigurationImportSelector.class),而AutoConfigurationImportSelector.class做了什么呢?通过其源码可以看出关键的部分为,

@Override
public 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());
}

其中,getAutoConfigurationEntry方法获取了spring-boot项目中需要自动配置的项(bean),查看其源码发现,

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

其中最重要的部分为getCandidateConfigurations方法,它获取了所有可能参与到项目的候选配置bean,与之对应的,getExclusions获取了所有不需要加载的配置bean。进一步查看getCandidateConfigurations方法的源码,

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	List<String> 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;
}

这个方法的具体实现为,读取spring-boot项目的classpath下META-INF/spring.factories的内容,这个文件常常以K/V的形式存储数据,例如:

# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.HelloAutoConfiguration,\
……

getCandidateConfigurations方法获取需要自动配置的类,除去上面讲到的需要排除(exclude)的配置类,其他类将会注册到spring-boot项目的spring容器中。

看到这里,想必已经了解@EnableAutoConfiguration注解的工作原理,回到最初的话题,“为什么要写spring.factories文件?”

结合前面提出的疑问——“在spring-boot项目中pom文件里面添加的依赖中的bean是如何注册到spring-boot项目的spring容器中的呢?”,不难得出spring.factories文件是帮助spring-boot项目包以外的bean(即在pom文件中添加依赖中的bean)注册到spring-boot项目的spring容器的结论。由于@ComponentScan注解只能扫描spring-boot项目包内的bean并注册到spring容器中,因此需要@EnableAutoConfiguration注解来注册项目包外的bean。而spring.factories文件,则是用来记录项目包外需要注册的bean类名。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: spring.factories可以用来注册到Spring容器中的bean,以便在应用程序启动时自动配置。例如,当spring.factories文件包含以下条目时,将自动注册com.example.MyBean到Spring容器中: org.springframework.context.annotation.Configuration=com.example.MyBean ### 回答2: spring.factoriesSpring框架中的一个重要文件,用于定义自动装配的配置。其作用类似于META-INF/services目录下的Java SPI机制,用于自动扫描并加载Spring应用程序中的配置文件。 具体来说,spring.factories文件是在jar包的META-INF目录下,在文件中可以定义各个模块的配置类。下面是一个spring.factories文件的示例: ``` # Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.myapp.config.MyConfig # Custom Bean Definition org.springframework.context.annotation.ImportSelector=\ com.example.myapp.config.CustomImportSelector ``` 上面的示例中,定义了两个关键的配置项。 第一个配置项`org.springframework.boot.autoconfigure.EnableAutoConfiguration`指定了一个自动装配配置类`com.example.myapp.config.MyConfig`。当Spring应用程序启动时,该配置类会被自动加载,其中可以定义一些自动装配的规则和@Bean注解的类。 第二个配置项`org.springframework.context.annotation.ImportSelector`指定了一个自定义的ImportSelector类`com.example.myapp.config.CustomImportSelector`。ImportSelector是一个接口,实现了该接口的类可以在该接口方法中动态地选择需要导入的配置类。通过在spring.factories文件中指定ImportSelector类,可以灵活地导入和组合各种配置类。 总结来说,spring.factories文件通过定义各个模块的配置项,实现了Spring在应用启动时自动加载和组合配置类的功能。这样可以方便地进行自动装配和配置的管理,提高了开发效率和灵活性。 ### 回答3: spring.factoriesSpring Boot框架中的一个配置文件,用于自动装配和加载Spring Boot提供的各种功能。 首先,我们需要新建一个META-INF/spring.factories文件,并将其放置在classpath下的resources目录中。然后在spring.factories文件中,可以通过键值对的形式配置Spring Boot的自动装配类。 一个使用spring.factories的例子是配置自定义的Starter。在Spring Boot中,Starter是一种约定的依赖,它可以自动带入所需的依赖和配置,以快速启动一个特定的功能。例如,假设我们打算开发一个自定义的邮件功能,我们可以创建一个新的Starter项目。 首先,我们在Starter项目的resources目录下新建META-INF/spring.factories文件,并在其中配置自动装配类的全限定名,例如: org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.custommail.CustomMailAutoConfiguration 在CustomMailAutoConfiguration类中,我们可以配置自定义的邮件相关的bean、属性等。通过在spring.factories中配置CustomMailAutoConfiguration的自动装配,Spring Boot会自动将相应的bean和配置导入到应用程序中,方便我们直接使用。 另一个例子是配置自定义的自动配置类。自动配置类是Spring Boot中的一个重要概念,用于自动装配和配置各种功能。我们可以通过在spring.factories文件中配置自定义的自动配置类,实现快速实现自定义功能的目的。 总之,spring.factoriesSpring Boot中用于配置自动装配类的配置文件。通过在其中配置相应的类,我们可以方便地实现自定义的Starter和自动配置,提供更多的扩展和功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值