在 Spring Boot 项目中,怎样将 pom.xml 文件里面添加的依赖中的 bean 注册到 Spring Boot 项目的 Spring 容器中呢?
你可能会首先想到使用 @ComponentScan 注解,遗憾的是 @ComponentScan 注解只能扫描 Spring Boot 项目包内的 bean 并注册到 Spring 容器中,项目依赖包中的 bean 不会被扫描和注册。此时,我们需要使用 @EnableAutoConfiguration 注解来注册项目依赖包中的 bean。而 spring.factories 文件,可用来记录项目包外需要注册的 bean 类名。
使用 spring.factories 文件有什么好处呢?假如我们封装了一个插件,该插件提供给其他开发人员使用。我们可以在 spring.factories 文件中指定需要自动注册到 Spring 容器的 bean 和一些配置信息。使用该插件的开发人员只需少许配置,甚至不进行任何配置也能正常使用。
我们以 spring-cloud-netflix-eureka-server 为例,该依赖用来实现 Eureka server 服务,它的 jar 包结构如下:

打开 spring.factories 文件,该文件内容如下:

该文件仅有一个 EnableAutoConfiguration 配置信息,而 EnableAutoConfiguration 用来启用 Spring Application Context 的自动配置,尝试猜测和配置您可能需要的 bean。通常根据您的类路径和定义的 bean 来应用自动配置类。上面配置文件将自动执行 EurekaServerAutoConfiguration 类,然后注册到 Spring 容器。源码如下:
@Configuration(
proxyBeanMethods = false
)
@Import({EurekaServerInitializerConfiguration.class})
@ConditionalOnBean({Marker.class})
@EnableConfigurationProperties({EurekaDashboardProperties.class, InstanceRegistryProperties.class})
@PropertySource({"classpath:/eureka/server.properties"})
public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
private static final String[] EUREKA_PACKAGES = new String[]{"com.netflix.discovery", "com.netflix.eureka"};
@Autowired
private ApplicationInfoManager applicationInfoManager;
//...
}示例
我们将演示 spring.factories 文件的用法,以及介绍该文件中可以配置那些 Bean。内容如下:
## Initializers org.springframework.context.ApplicationContextInitializer=\ com.huangx.springboot.autoconfig.MyApplicationContextInitializer ## Application Listeners org.springframework.context.ApplicationListener=\ com.huangx.springboot.autoconfig.MyApplicationListener ## Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ com.huangx.springboot.autoconfig.MyAutoConfigurationImportListener ## Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ com.huangx.springboot.autoconfig.MyConfigurationCondition ## Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.huangx.springboot.autoconfig.MyConfiguration ## Failure analyzers org.springframework.boot.diagnostics.FailureAnalyzer=\ com.huangx.springboot.autoconfig.MyFailureAnalyzer ## Template availability providers org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\ com.huangx.springboot.autoconfig.MyTemplateAvailabilityProvider
下面将分别介绍各种配置的具体含义:
ApplicationContextInitializer
该配置项用来配置实现了 ApplicationContextInitializer 接口的类,这些类用来实现上下文初始化。配置如下:
org.springframework.context.ApplicationContextInitializer=\ com.huangx.springboot.autoconfig.MyApplicationContextInitializer
实例代码:
public class MyApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("MyApplicationContextInitializer.initialize() " + applicationContext);
}
}ApplicationListener
配置应用程序监听器,该监听器必须实现 ApplicationListener 接口。它可以用来监听 ApplicationEvent 事件。配置如下:
org.springframework.context.ApplicationListener=\ com.huangx.springboot.autoconfig.MyApplicationListener
实例代码:
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("MyApplicationListener.onApplicationEvent() " + event);
if(event instanceof ApplicationStartedEvent) {
throw new RuntimeException("我故意抛出的错误,仅仅为了触发自定义 MyFailureAnalyzer");
}
}
}AutoConfigurationImportListener
该配置项用来配置自动配置导入监听器,监听器必须实现 AutoConfigurationImportListener 接口。该监听器可以监听 AutoConfigurationImportEvent 事件。配置如下:
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ com.huangx.springboot.autoconfig.MyAutoConfigurationImportListener
实例代码:
public class MyAutoConfigurationImportListener implements AutoConfigurationImportListener {
@Override
public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {
System.out.println("MyAutoConfigurationImportListener.onAutoConfigurationImportEvent() " + event);
}
}AutoConfigurationImportFilter
配置自动配置导入过滤器,过滤器必须实现 AutoConfigurationImportFilter 接口。该过滤器用来过滤那些自动配置类可用,配置信息:
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ com.huangx.springboot.autoconfig.MyConfigurationCondition
实例代码:
public class MyConfigurationCondition implements AutoConfigurationImportFilter {
@Override
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
System.out.println("MyConfigurationCondition.match() autoConfigurationClasses=" +
Arrays.toString(autoConfigurationClasses) +
", autoConfigurationMetadata=" + autoConfigurationMetadata);
return new boolean[0];
}
}EnableAutoConfiguration
配置自动配置类。这些配置类需要添加 @Configuration 注解,配置如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.huangx.springboot.autoconfig.MyConfiguration
实例代码:
@Configuration
public class MyConfiguration {
public MyConfiguration() {
System.out.println("MyConfiguration()");
}
}FailureAnalyzer
配置自定的错误分析类,该分析器需要实现 FailureAnalyzer 接口。配置信息:
org.springframework.boot.diagnostics.FailureAnalyzer=\ com.huangx.springboot.autoconfig.MyFailureAnalyzer
实例代码:
/**
* 自定义自己的错误分析器 FailureAnalyzer
* @author Administrator 2021/4/1 13:14
* @version 1.0
*/
public class MyFailureAnalyzer implements FailureAnalyzer {
@Override
public FailureAnalysis analyze(Throwable failure) {
System.out.println("MyFailureAnalyzer.analyze() failure=" + failure);
return new FailureAnalysis("MyFailureAnalyzer execute", "test spring.factories", failure);
}
}运行效果如下图:

TemplateAvailabilityProvider
配置模板的可用性提供者,提供者需要实现 TemplateAvailabilityProvider 接口,配置如下:
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\ com.huangx.springboot.autoconfig.MyTemplateAvailabilityProvider
实例代码:
/**
* 验证指定的模板是否支持
* @author Administrator 2021/4/1 13:22
* @version 1.0
*/
public class MyTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
@Override
public boolean isTemplateAvailable(String view, Environment environment,
ClassLoader classLoader, ResourceLoader resourceLoader) {
System.out.println("MyTemplateAvailabilityProvider.isTemplateAvailable() view=" +
view + ", environment=" + environment + ", classLoader=" + classLoader +
"resourceLoader=" + resourceLoader);
return false;
}
}