SpringBoot自动配置&&自动加载controller的原理.md
好久没有更新自己的博客了,自己最近的正好有点空闲的时间进行,自己在写着写着,突然想起来,
为什么我们点击
application
就能自动加载@Controller
呢?(好家伙,我顿时鱼鳃,哈哈)
1.首先我们来到启动现场===>启动类
@SpringBootApplication
public class TestApplication extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(ActAfterApplication.class);}public static void main(String[] args) {SpringApplication.run(ActAfterApplication.class, args);}
}
我们会看到在TestApplication
启动类上会有一个注解:@SpringBootApplication
这个注解,就是我们今天的文章的核心,核心**,核心**!!!=====>你可能会说,我问怎么加载@Controller
d的,你给我看这些干啥子?别急啊!大白(●—●),我们向下看
2.@SpringBootApplication
剖析
首先我们看点击这个注解进去的当中的三个关键注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
====> 这个注解就是我们为什么Spring
会加载@Controller
组件关键所在
@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 {
3.@SpringBootConfiguration
:
这个注解作用标明此类为配置类,点进去发现就是
@Configuration
,在加载时加载到Spring IOC
中你就把他想成是一个让他拥有配置的角色的作用就行啦===> 给他套个龙袍,当太子
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration //就是这个注解最关键=====================================
public @interface SpringBootConfiguration {}
4.@EnableAutoConfiguration
**作用:**这个注解可以说是
Springboot
的灵魂,自动配置,也就是将我们配置文件配置的配置类都加载进来,它会扫描
jar
包下面的META-INF/spring.factories
文件,将所有符合条件的自动配置类加载到IOC
容器中====>是自动配置的核心为什么?我们点进源码去看看呗,如下的源码,我们会看其中有两个核心的注解 (就是自动配置的关键,这两个注解说明,可以不看,忽略直接看下一个核心注解)
1.
@AutoConfigurationPackage
2.
@Import(AutoConfigurationImportSelector.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
4.1 @AutoConfigurationPackage
点击源码,我们会看到其中的一个:
@Import(AutoConfigurationPackages.Registrar.class)
**作用:**借助
@Import
注解导入符合自动配置类的集合,目的为了加载到IOC
容器中
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
AutoConfigurationPackages.Registrar.class
的源码,这个可以直接忽略,感兴趣的可以看看
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {register(registry, new PackageImport(metadata).getPackageName()); //获取包名}@Overridepublic Set<Object> determineImports(AnnotationMetadata metadata) {return Collections.singleton(new PackageImport(metadata));}}
4.2@Import(AutoConfigurationImportSelector.class)
这个类就更重要了,问什么这样说?让我们结合下面的源码一起解读(为了阅读的便利性,只保留所需源码的核心块)
- 根据引入的
AutoConfigurationImportSelector
中的selectImports
方法,- 读取所有依赖的
jar
包下面也就是META-INF/spring.factories
下面的文件(怎么借加载此目录下面的呢?===>请看getCandidateConfigurations
讲解)- 并且根据加载的条件加载项目所需要的类
通过这三个步骤,也就完成
SpringBoot
的自动加载 ===> 从而@AutoConfigurationPackage
执行结束
public class AutoConfigurationImportSelectorimplements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,BeanFactoryAware, EnvironmentAware, Ordered {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);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 StringUtils.toStringArray(configurations);}
getCandidateConfigurations
:
为了便于确认,我将
AutoConfigurationImportSelector
类下面此方法单独拎出来z这个方法会读取所有的’
META-INF/spring.factories
’的依赖jar
包,获取
spring.factories
全名称,====.>其实下面的注解也写了 >点击loadFactoryNames
方法,> 加载META-INF/spring.factories
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;}
5.@ComponentScan
前面的两个注解说完了,我们终于来到此注解,也是解开我心里疑惑的注解了
就特么我解释吗?===> 就是将我们注册
@Controller
,@Service
,等注解自动扫描加到IOC
容器中
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
6.META-INF/spring.factories
这个到底是什么鬼东西???说了半天,我们去看看,其实写这篇博客,按自己也很好奇,哈哈哈
我们走,一起去看看
https://blog.csdn.net/weixin_40017062/article/details/128710518