自动配置原理
关键注解@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
注解
这个注解会扫描和加了这个注解的类在同一包和子包下的所有组件即:Controller
、service
等,为我们省去了写xml配置文件的过程),再点击进入@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 {};
}
这个注解有2个方法: exclude 和 excludeName,在@SpringBootApplication
中可以通过使用这两个方法来指明我们不想自动注入的类
比如:我们不想让springBoot自动配置数据源(springBoot默认HikariCP连接池),这样可以自己注入数据源,达到切换连接池的目的
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ForumServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ForumServiceApplication.class, args);
}
}
@Import(AutoConfigurationImportSelector.class)
,@import
注解表示引入指定类型的bean,即AutoConfigurationImportSelector
,SpringBoot为我们自动注入的
bean全部通过它来读取,点击进入AutoConfigurationImportSelector
源码
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());
}
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);
}
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;
}
}
getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
AutoConfigurationImportSelector
通过getAutoConfigurationEntry
这个方法获取到需要自动注入的类,getAutoConfigurationEntry
又调用了getCandidateConfigurations(annotationMetadata,attributes)
,getCandidateConfigurations
调用SpringFactoriesLoader
类的静态方法,进入SpringFactoriesLoader
中,这个类是spring-core包中的
public final class SpringFactoriesLoader {
/**
* The location to look for factories.
* <p>Can be present in multiple JAR files.
*/
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
}
自动配置核心文件
通过源码注释可以看到 FACTORIES_RESOURCE_LOCATION
,并且位置为META-INF/spring.factories
, spring.factories
是本文重点
部分spring.factories内容:
# 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.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
下面所有的自动配置类将被springBoot自动注入,通过spring.factories
我们可以自定义自动配置类,实现springboot容器启动时自动注入的效果