一、理解 spring-boot-starter 自动装配
大家都知道使用 spring-boot-starter 可以简化日常开放中的配置,那么大家是否好奇,这些简化的配置SpringBoot是怎么为我们的应用自动装配的呢?带着疑问,一起来看看SpringBoot的自动装配功能吧。
- 理解 @SpringBootApplication 启动类注解
1.1 @SpringBootApplication 由以下三个关键注解组成
@SpringBootConfiguration // 该注解与 @Configuration 无异
@ComponentScan // 该注解用于激活注解扫描
@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 {};
}
@EnableAutoConfiguration注解中使用 @Import({AutoConfigurationImportSelector.class}) ,导入了AutoConfigurationImportSelector类。
由于AutoConfigurationImportSelector 是 ImportSelector 接口的子类,所以直接看 AutoConfigurationImportSelector#selectImports() ,如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@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 方法是如何实现的
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() 方法实现
大家可以看到,重点是获取准备装配的配置类集合方法 getCandidateConfigurations() 进一步往下看会看到,程序会去加载根目录下的 META-INF/spring.factories 文件,META-INF/spring.factories 如下所示:
可以看到 META-INF/spring.factories 是一个properties文件,其中
org.springframework.boot.autoconfigure.EnableAutoConfiguration
对应的value则是SpringBoot自动装配的配置类,包括我们常见的数据库自动装配 DataSourceAutoConfiguration和RedisAutoConfiguration自动装配等。这样就可以做到我们在application.properties文件中只需配置数据库与redis的连接信息就可以使用了。
二、自定义开发 spring-boot-starter
1、新建项目customer-spring-boot-starter
- 添加一个 CustomerAutoConfiguration 配置类,并注册一个 String 类型的bean
- 在根目录下新建 /META-INF/spring.factories文件,并配置上一步的新增的配置类 CustomerAutoConfiguration
2、新建一个测试项目 test 并在pom文件中引用 customer-spring-boot-starter
可以看到控制台输入的张三,就是我们自动装配的bean,自定义开发Spring-boot-starter就是这么简单 !
源码地址:https://github.com/yuhuangbin/spring-boot-starter-sample