什么是SpringBoot自动装配?
SpringBoot方便在于我们需要第三方依赖直接引入starter即可,通过少量的注解和一些简单的配置就能使用第三方组件的功能。SpringBoot的核心就在于自动装配,带来了极大地方便。
SpringBoot是如何自动装配?
SpringBoot 的核心注解 @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 {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
// 根据包路径扫描
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
// 直接根据class类扫描
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@SpringBootApplication
看作是 @Configuration
、@EnableAutoConfiguration
、@ComponentScan
注解的集合。
@Configuration
:允许在上下文中注册额外的 bean 或导入其他配置类。@EnableAutoConfiguration
:代表开启springboot的自动装配。@ComponentScan
:自动扫描并加载符合条件的组件或bean定义,最终将这些bean定义加载到容器中。
关于@EnableAutoConfiguration
实现自动装配注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
// 加载自动装配类 xxxAutoconfiguration
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
//按类型排序不需要自动装配的类
Class<?>[] exclude() default {};
//按名称排除不需要自动装配的类
String[] excludeName() default {};
}
重点看看AutoConfigurationImportSelector 类做了什么
private static final String[] NO_IMPORTS = {};
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 自动装配是否打开
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 获取所有需要装配的bean
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
getAutoConfigurationEntry()
方法主要负责加载自动配置类。
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
// 1.判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 2.用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 3.获取需要自动装配的所有配置类,读取META-INF/spring.factories
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 4.这一步有经历了一遍筛选,@ConditionalOnXXX 中的所有条件都满足,该类才会生效。
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
-
判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置
-
用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
-
获取需要自动装配的所有配置类,读取META-INF/spring.factories
从下图可以看到这个文件的配置内容都被我们读取到了。XXXAutoConfiguration的作用就是按需加载组件。
不光是这个依赖下的META-INF/spring.factories被读取到,所有 Spring Boot Starter 下的META-INF/spring.factories都会被读取到。
所以,你可以清楚滴看到, druid 数据库连接池的 Spring Boot Starter 就创建了META-INF/spring.factories文件。
- spring.factories中这么多配置,不是每次启动都要全部加载。
经历了一遍筛选,@ConditionalOnXXX 中的所有条件都满足,该类才会生效。