前言:不忘初心,寻找最初的编程快感!
时序图
分析
- @SpringBootApplication注册程序入口,是@SpringBootConfiguration丶@EnableAutoConfiguration
和@ComponentScan的并集
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MySpringBootApplication.class);
application.run();
}
}
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
- @SpringBootConfiguration继承至@Configuration,二者差不多功能一致,标注当前类是配置类,
并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名。
@SpringBootConfiguration
public class SpringBootConfigurationTestConfig {
@Bean
public String testConfig(){
return "testConfig......";
}
}
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MySpringBootApplication.class);
ConfigurableApplicationContext context = application.run();
System.out.println(context.getBeanFactory().getBean("testConfig"));
}
}
- 最主要的还是@EnableAutoConfiguration,打开自动配置,可以通过设置注解的excludeName属性或者通过spring.autoconfigure.exclude配置项来指定不需要自动配置的项目。
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
- AutoConfigurationImportSelector实现了selectImports() 方法,用来筛选被@Import的Configuration类(减去exclude等)
- org.springframework.boot.autoconfigure.AutoConfigurationImportSelector类图:
- Spring boot发现注解中存在@Import(ImportSelector)的情况,就会创建一个相应的ImportSelector对象, 并调用其方法 public String[] selectImports(AnnotationMetadata annotationMetadata),如下是相关源码解析:
protected boolean isEnabled(AnnotationMetadata metadata) {
return this.getClass() == AutoConfigurationImportSelector.class ? (Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, true) : true;
}
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
//根据spring-boot-autoconfigure包下的spring-autoconfigure-metadate.properties中的配置加载配置元数据
//loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
//
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
//获取@EnableAutoConfiguration配置类名称及exclude属性
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//从spring-boot-autoconfigure包里面META-INF/spring.factories加载配置类的名称
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
//去重处理,LinkedHashSet去重
configurations = this.removeDuplicates(configurations);
//获取自动配置排除类
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
//检查排除类是否是auto-configuration classes
this.checkExcludedClasses(configurations, exclusions);
//去除自动配置排除类
configurations.removeAll(exclusions);
//过滤掉配置未配置@OnClassCondition的自动配置类,当检测存在输入的类时候,该配置类生效,否则将不被实例化;
//AutoConfigurationImportFilter -> FilteringSpringBootCondition.match -> OnClassCondition.getMatchOutcome
configurations = this.filter(configurations, autoConfigurationMetadata);
//激活配置ConditionEvaluationReportAutoConfigurationImportListener.onAutoConfigurationImportEvent
this.fireAutoConfigurationImportEvents(configurations, exclusions);
//返回AutoConfigurationEntry配置信息
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
小结
Spring Boot的自动化配置提供了十分方便的开发方式,但任何东西都可能有其两面性的存在,“欲思其利,必虑其害,欲思其成,必虑其败”,实际使用中还得多注意细枝末节,要做到更灵活丶更高效地使用手中的利剑;