一、什么是自动装配
SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到 Spring 容器(此处涉及到 JVM 类加载机制与 Spring 的容器知识),并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot。
记住这个spring.factories文件,我们在下面自定义starter启动器是会需要它。
1.1 自动装配的使用
没有 Spring Boot 的情况下,如果我们需要引入第三方依赖,需要手动配置,非常麻烦。但是,Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
引入starter之后,我们可以通过少量的注解和一些简单的配置就能使用第三方组件提供的功能了。
二、自动装配的实现
自动装配的实现,离不开@SpringBootApplication这个核心注解。
2.1 @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 {
其中,有三个注解是需要我们注意的:
- @Configuration
允许在上下文中注册额外的 bean 或导入其他配置类
- @EnableAutoConfiguration
启用 SpringBoot 的自动配置机制
- @ComponentScan
扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。如下图所示,容器中将排除TypeExcludeFilterh和AutoConfigurationExcludeFilter。

2.2 @EnableAutoConfiguration
字面意思来看,该注解是启动自动配置,事实上,@EnableAutoConfiguration也确实是实现自动装配的重要注解。
下面来看下enableAutoConfiguration注解的内容:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
其中AutoConfigurationImportSelector类是加载自动装配类;
AutoConfigurationImportSelector类的结构体系如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
}
其中,实现的ImportSelector接口中,有一个selectorImports方法也被实现了,该方法主要用于获取所有符合条件的类的全限定类名,然后将这些类加载到Ioc容器中,该方法的具体实现如下:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
然后,再来看下其中的getAutoConfigurationEntry()方法,这个方法主要用于加载自动装配类,方法的实现如下:
/**
* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
* of the importing {@link Configuration @Configuration} class.
* @param annotationMetadata the annotation metadata of the configuration class
* @return the auto-configurations that should be imported
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//step1
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//step2
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//step3
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
//step4
}
下面来分析下getAutoConfigurationEntry()方法的源码:
- 判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置。
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}

- 用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
AnnotationAttributes attributes = getAttributes(annotationMetadata);

- 获取需要自动装配的所有类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

所以,如果,我们自己要创建一个 Spring Boot Starter,这一步是必不可少的:

- 筛选不需要加载的配置
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
三、自己实现starter
可以参考我的另外一篇博客:
四、参考
https://www.cnblogs.com/javaguide/p/springboot-auto-config.html
本文详细解析了SpringBoot的自动装配机制,从自动装配的使用到其实现,深入探讨了@SpringBootApplication和@EnableAutoConfiguration注解的作用。通过分析AutoConfigurationImportSelector类,揭示了自动装配类的加载过程。此外,还介绍了如何自定义starter,并提供了相关资源链接供进一步学习。
2349

被折叠的 条评论
为什么被折叠?



