引导加载自动配置类
总注解@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication
@SpringBootConfiguration
,本质上就是@Configuration
。@ComponentScan
,指定包扫描路径。@EnableAutoConfiguration
部分源码如下:
(1)注解@AutoConfigurationPackage // 自动注册@SpringBootApplication类所在包的bean
@Import(AutoConfigurationImportSelector.class) // 自动导入所有符合自动配置条件的bean并加载到容器
public @interface EnableAutoConfiguration
@AutoConfigurationPackage
给IOC容器中导入了一个Registrar
组件:@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage
Registrar
实现了ImportBeanDefinitionRegistrar
接口与,目的就是向IOC容器了批量注册@SpringBootApplication
标注类所在包下的所有组件。
(2)static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override // 批量注册组件
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// new PackageImport(metadata).getPackageName()
// => @SpringBootApplication标注类所在的包
register(registry, new PackageImport(metadata).getPackageName());
// 批量注册这个包下的组件
}
}
@Import(AutoConfigurationImportSelector.class)
通过@Import
注解向IOC容器中导入自动配置选择器组件。 ```java // [AutoConfigurationImportSelector]
// 1. 获取所有自动配置 selectImports() => getAutoConfigurationEntry()
// 2. 获取所有需要导入到容器中配置类 getAutoConfigurationEntry() => getCandidateConfigurations()
// 3. 获取配置类后,移除重复,排除一些,过滤一些,检查一下
// [SpringFactoriesLoader]
// 4. 使用SpringFactoriesLoader加载 getCandidateConfigurations() => SpringFactoriesLoader.loadFactoryNames()
// 5. 从META-INF/spring.factories位置加载文件,默认扫描当前系统里面所有META-INF/spring.factories loadFactoryNames() => loadSpringFactories()
Enumeration
// 核心:所有spring-boot-autoconfigure包下的META-INF/spring.factories文件,所有关于org.springframework.boot.autoconfigure的配置项
用一张图总结一下:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/493248/1641956307051-b982c356-96af-497e-ac0a-2387d86364fb.png#clientId=uca1b03bf-bafb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=580&id=ucb7f4611&margin=%5Bobject%20Object%5D&name=image.png&originHeight=580&originWidth=1440&originalType=binary&ratio=1&rotation=0&showTitle=false&size=102060&status=done&style=shadow&taskId=u1a86891c-3d20-40a2-ae21-946944b54db&title=&width=1440)
<a name="EWXcK"></a>
## 按需开启自动配置项
虽然spring.factories的自动配置项默认全部加载,但是最终会按需配置。<br />拿`AopAutoConfiguration`的内部类举例,条件装配:
- `@ConditionalOnClass`:必须导入相关依赖才能生效
- `@ConditionalOnProperty`:必须配置文件中配置才能生效
```java
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration { }
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
static class CglibAutoProxyConfiguration { }
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice") // 缺失这个类时生效
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) // 默认开启AOP
static class ClassProxyingConfiguration {
ClassProxyingConfiguration(BeanFactory beanFactory) {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
}