引导加载自动配置类
总注解@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 /><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) // 默认开启AOPstatic class ClassProxyingConfiguration {ClassProxyingConfiguration(BeanFactory beanFactory) {if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}}}}
