文章目录

  • 第一个注解:@SpringBootApplication
  • 点进去有一堆注解:
  • 1.这4个是元注解:
  • 2.@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
  • 3.@AutoConfigurationPackage @Import:
  • 4.我们先进input的类里面看看
  • 5.getCandidateConfigurations:翻译:获取候选配置
  • 6.我们把方法拿下来这照着看
  • 7.开始参数:第一个getSpringFactoriesLoaderFactoryClass():翻译 获取Spring Factory Loader Factory类
  • 8.getBeanClassLoader():获取Bean类加载器 简洁,大气,一个加载器(我不懂,我猜他是自带的,应该也不需要我懂吧)
  • 9.spring.factories:头皮发麻 好多东西
  • 10.好了回到老地方
  • 11.input走完了:总结就是获取到了"META-INF/spring.factories"配置文件中的所有自动配置类
  • 12.回顾一下思路
  • 13.差不多就springboot的流程了 ---自动配置
  • 14.@AutoConfigurationPackage:现在看看这个
  • 15.呦西,这里是扫描我们的jar包的地方吧
  • 16.总结:

第一个注解:@SpringBootApplication

1.表示这是一个springboot的应用
2.指示一个配置类,该类声明一个或多个@Bean方法并触发自动配置和组件扫描。
这个类会触发自动配置和组件扫描。
3.这是一个方便的注释,相当于声明@Configuration、@EnableAutoConfiguration和@ComponentScan。
这是一个组合注解,就是@Configuration、@EnableAutoConfiguration和@ComponentScan的合并

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

点进去有一堆注解:

@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 {

1.这4个是元注解:

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited
@Target(ElementType.TYPE)表示这个自定义的注解(@interface SpringBootApplication)可以用在什么地方;
TYPE就是接口,类等上面,就不要用在属性上了
@Retention(RetentionPolicy.RUNTIME):就是会不会被编译器编译,比如@test是不会编译的
@Documented:就是可以做成doc文档
@Inherited:就是这个自定义的注解可以继承,父类用了这个注解,子类也生效

2.@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan

@ComponentScan:这个就不说了,就是这个扫描包嘛,Filter过滤了一些包,其他的都可以注册到bean中
@SpringBootConfiguration :点进来就是这样,除了元注解就是一个@Configuration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

@Configuration:这里面就是一个@Component,一个普通的注册到bean的类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

@EnableAutoConfiguration:重点就是这个了,其他的都看完了,只剩这个了,点进去

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

3.@AutoConfigurationPackage @Import:

@Import:
导入什么东西,在配置xml的时候也有,就是把什么东西连接到这里的意思嘛
这里肯定就是把AutoConfigurationImportSelector.class这个类都加载,
差不多就是给这个**@EnableAutoConfiguration**搞了个子类的意思
EnableAutoConfiguration有个子类是AutoConfigurationImportSelector

4.我们先进input的类里面看看

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

就是一个类AutoConfigurationImportSelector翻译英文就是自动配置导入选择器
名字的意思就是选择器,要导入哪个类型的自动配置类,应该有个相应的选择器去帮我们判断到底是哪个配置类
意思就是,我们maven导包了,他查看我们导的包,去加载对应的配置类嘛
看看到底是哪个方法搞的

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.getCandidateConfigurations:翻译:获取候选配置

这不就是获取到底是那个配置类嘛

**理一下前面的思路先:**我们进了@SpringBootApplication注解看了他的注解只有一个有用
其他的元注解,扫描包什么都没什么大用,我们现在的位置就是@EnableAutoConfiguration 自动配置注解这里面
有@AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) 我们在input类这里,还有个注解等会看

回到上面:getCandidateConfigurations方法
他的返回值是一个list,是configurations,看名字就是很多个配置类的意思好像
他用了SpringFactoriesLoader类里的方法loadFactoryNames:翻译加载工厂名称
听不懂哈,好像是要获得一些名字吧,我们去读一下这个方法的文档注释(就是点进去看看注释哈)

从“META-INF”加载给定类型的工厂实现的完全限定类名/春季工厂,使用给定的类装入器。
从springframework5.3开始,如果一个特定的实现类名对于给定的工厂类型被发现不止一次,那么重复的类名将被忽略。
参数:
表示工厂的接口或抽象类 类
加载器-用于加载资源的类加载器;可以为null以使用默认值

6.我们把方法拿下来这照着看

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());

读注释:
他会从“META-INF”什么东西里加载一个完全限定类名/春季工厂
大概就是从这“META-INF”找这些类吧(我连“META-INF”是啥都不知道)
然后用什么给定的类装入器,也听不懂哈,慢慢搞哈
5.3开始后,如果类重复了就忽略,就是不能重复加载类,我读懂了

7.开始参数:第一个getSpringFactoriesLoaderFactoryClass():翻译 获取Spring Factory Loader Factory类

哦,就是用这个方法去获取“META-INF”里面的类,我又懂了
后面的参数getBeanClassLoader等会再看,我们先进这里面看看;

 protected Class<?> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;}

古德:非常简单,就是返回了一个EnableAutoConfiguration的class
哟咋这么眼熟;EnableAutoConfiguration
我们先进@SpringBootApplication,然后马上就来了个@EnableAutoConfiguration注解,我们点进去这里面才到input的
然后我们在input类里面点了方法,现在获取什么完全限定类名又绕回来了
现在他又给我返回来了咋回事,我思考下
我们是在input里面的,input相当于EnableAutoConfiguration的子类,也就是我们在子类中调用了父类,没毛病

我还发现了个秘密,你看没想到

 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;}protected Class<?> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;}

getSpringFactoriesLoaderFactoryClass()方法就这这个获取候选配置方法的下面
接着前面我们讲了第一个参数,现在第二个

8.getBeanClassLoader():获取Bean类加载器 简洁,大气,一个加载器(我不懂,我猜他是自带的,应该也不需要我懂吧)

纳,现在好像什么都没得到;两个参数,一个返回了EnableAutoConfiguration,一个没啥用
我们进方法里看一下,到底是怎么获取到配置类,一堆配置类

 private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {// 搞了个map,不用懂太多,知道有个map就行Map<String, List<String>> result = cache.get(classLoader);//如果为空:就返回,猜猜意思//大概就是,从这里就已经读到了上面“META-INF”里的配置类,如果什么都没读到,就返回空,正常//现在还不知道“META-INF”里的东西是什么呢if (result != null) {return result;}
//又new了一个map,这个就很明显了,重新高了一个空的,证明了上面确实应该读到了一些东西result = new HashMap<>();try {//classLoader这个又来了,一个加载器,获取资源getResources,FACTORIES_RESOURCE_LOCATION一个常量//点进常量看看,代码再下面;"META-INF/spring.factories"//噢,"META-INF这个终于出现了,//getResources就是获取META-INF/spring.factories,spring.properties里的东西//我们也找找这个东西在那里,想进去看看,但是我发现,,我好像不知道它在哪里?尴尬...\//想办法找,他没写绝对路径,肯定有个默认的路径,我们要找到那个默认的路径再找META-INF/spring.factories//我猜默认的路径应该就是这个常量所在的类的包里面,因为配置文件properties肯定在包里了,反正正常的地方肯定没有的//我点进去看了看,有META-INF文件夹,没有spring.factories文件,稳了,肯定在其中一个包里,要不要一个一个找一下//不,我觉得肯定有准确的位置的,我想想,既然常量所在的类没有,我在这个方法里又调用了这个常量//会不会在我这个方法所在的包中,我滑到最上面,找到package org.springframework.boot.autoconfigure;//点进去,古德,我看见了META-INF/spring.factories,截图在下面,点进去spring.factories看看,截图也附加再下面//现在就懂了,它把那个文件里那么多类似key=value的东西搞出来放在了这里EnumerationEnumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);//hasMoreElements:翻译有更多元素 如果有更多,就继续循环while (urls.hasMoreElements()) {//下一个,这里就是把刚刚properties中的东西,一个一个的赋值URL url = urls.nextElement();//new一个UrlResource:把取出来的放进去UrlResource resource = new UrlResource(url);//又套娃,把在放进去的东西又放到一个Properties 中//与前面不一样,前面应该每次循环都会创建new一个UrlResource,而这里只是放进去,应该可以放很多个//配合他的名字properties,应该也是类似一个properties的文件,key-valueProperties properties = PropertiesLoaderUtils.loadProperties(resource);//entrySet遍历,把东西分出来,用一个一个的set接收for (Map.Entry<?, ?> entry : properties.entrySet()) {//getKey,分出来key;trim修剪,刚刚spring.properties中有\,这些东西,感觉是去掉这些东西的//修剪好了赋值stringString factoryTypeName = ((String) entry.getKey()).trim();//getValue,这里是要把value也分出来String[] factoryImplementationNames =StringUtils.commaDelimitedListToStringArray((String) entry.getValue());//又是一个遍历,变量分出来的value,刚刚在spring.properties中看到,一个key好像后面有很多value(xx=\,xx\,xx)for (String factoryImplementationName : factoryImplementationNames) {//result是上面的map,lambda,把factoryTypeName就是key存进去,用arraylist接收//然后又add把factoryImplementationName就是value修剪一下也存进map中//反正最后应该是把得到的所有配置类都放到了map中result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()).add(factoryImplementationName.trim());}}}
//后面做了什么计算,就不懂了,就不看了,反正知道他把所有配置类都放到了map中返回了// Replace all lists with unmodifiable lists containing unique elementsresult.replaceAll((factoryType, implementations) -> implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));cache.put(classLoader, result);}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}return result;}

上面代码中的常量:

 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

找到了"META-INF/spring.factories"

9.spring.factories:头皮发麻 好多东西

xxx=
xxx,
xxx
这什么格式?

好,回来了

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;}

loadFactoryNames:最后返回了一个map,咦它这里不是List configurations,list嘛
别搞我啊
噢噢噢,太绕了

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
方法里面是:```java
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {ClassLoader classLoaderToUse = classLoader;if (classLoaderToUse == null) {classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();}String factoryTypeName = factoryType.getName();return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());}

return loadSpringFactories(classLoaderToUse):loadSpringFactories才是map,在loadFactoryNames后变成了list

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {Map<String, List<String>> result = cache.get(classLoader);if (result != null) {return result;}result = new HashMap<>();try {

10.好了回到老地方

@Import(AutoConfigurationImportSelector.class)
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
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;}

11.input走完了:总结就是获取到了"META-INF/spring.factories"配置文件中的所有自动配置类

...
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
...

12.回顾一下思路

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
@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 {
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

好:**@Import(AutoConfigurationImportSelector.class)**走完了
其实也差不多了,springboot就是在input这里把我们所有的自动配置类都写好并且帮我们找到了

13.差不多就springboot的流程了 —自动配置

有始有终:

14.@AutoConfigurationPackage:现在看看这个

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

AutoConfigurationPackages:自动配置包
Registrar:登记员

 static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));}@Overridepublic Set<Object> determineImports(AnnotationMetadata metadata) {return Collections.singleton(new PackageImports(metadata));}}

自动配置包里面的一个静态内部类
看看注释:

importBeanDefinitionRegistrator存储导入配置中的基本包

15.呦西,这里是扫描我们的jar包的地方吧

16.总结:

@SpringBootApplication—>@EnableAutoConfiguration—>@Import(AutoConfigurationImportSelector.class)
这一条路是找到自动配置类的

@SpringBootApplication—>@EnableAutoConfiguration—>
@AutoConfigurationPackage—>@Import(AutoConfigurationPackages.Registrar.class)

这一条路就扫描maven包的

SpringBoot -> 自动装配初探,debug=ture判断配置类是否生效相关推荐

  1. SpringBoot 自动装配原理

    运行原理探究 我们之前写的HelloSpringBoot,到底是怎么运行的呢,Maven项目,我们一般从pom.xml文件探究起: 1.父依赖 pom.xml spring-boot-dependen ...

  2. 刨析 SpringBoot 自动装配原理,其实很简单

    J3 SpringBoot # 源码 # 自动装配 一日我在愉快得遨游时,看到有鱼友在问:SpringBoot 中引入了 Nacos 依赖为啥就可以直接使用 Nacos 中的相关功能呀! 认真思考了一 ...

  3. SpringBoot自动装配探究

    Spring Boot自动配置的探究 : 参考 配置文件能配置的属性参照 原理 SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 作用 ...

  4. 手写springboot自动装配 autoConfiguration

    springboot自动装配 + java敏感词匹配 1. 项目准备 deploy项目 :  https://gitee.com/hctrl/deploy word-spring-boot-start ...

  5. SpringBoot自动装配原理浅析

    Springboot自动装配原理 SpringBoot是当下J2EE最为流行的框架,它有着轻量,快捷等特点,让程序员们可以专注在业务逻辑的编写上,而不用花太多的力气在一些环境的配置,整合组件的配置上面 ...

  6. 【SpringBoot】Spring手动装配和SpringBoot自动装配

    文章目录 1. Warm up 1.1 setter注入 1.2 构造器注入 1.3 属性注入 2. Warm up again 2.1 基于XML的配置 2.2 基于JavaConfig类的配置 3 ...

  7. SpringBoot自动装配原理解析——面试可以这样会回答

    1. 前言 SpringBoot是目前软件中最主流的框架,无论是工作还是面试基本都有它的身影,SpringBoot主要解决了传统spring的重量级xml配置Bean,实现了自动装配:所以,我们也常在 ...

  8. Springboot自动装配源码分析

    Springboot自动装配源码分析 1.从@SpringbootApplication点进去 2.可以看到核心的三个注解 @SpringbootConfiguration @EnableAutoCo ...

  9. SpringBoot 自动装配原理解析

    自动装配是 Spring Boot 的核心部分,也是 Spring Boot 功能的基础,正是由于自动装配,才 将我们从 Bean 的繁复配置中解脱出来.那么 Spring Boot 中的自动装配指的 ...

最新文章

  1. 刘歧:FFmpeg Filter深度应用
  2. rocketmq4.1.0部署及流量切换实践
  3. Eclipse导入Android项目 Eclipse常见错误 中文乱码问题
  4. 光波函数和薛定谔方程
  5. 看了星球大战--西斯的复仇
  6. 空间点到空间直线的距离求解
  7. 计算机专业毕业论文写作指导(案例超详解)
  8. 校园民谣:1983-2003。谨以此文献给2020年说再见就此生再也不见的毕业生们
  9. 红警ol服务器维护中1003,红警OL频繁掉线怎们么办 网络断开连接解决办法
  10. 上海华谊(集团)公司-统一业务协同平台
  11. 西电计组II 实验1
  12. nginx与react配合二级路由
  13. 歇逼了兄弟,心态崩了
  14. 槛外人观察 :语义和语用
  15. FastFDS----分布式文件服务系统服务端搭建
  16. ZYNQ-7的芯片引脚
  17. Manjaro + Windows 双系统安装指南
  18. day21-pdf作业
  19. This app has crashed because it attempted to access privacy-sensitive data without a usage
  20. 299. Bulls and Cows

热门文章

  1. 【Unity入门】3.3D物体
  2. 淘宝 模拟 登录 总结 【QQ 346767073 】
  3. vue3组件之间通信(二)——子传父属性和方法
  4. 马赛克颗粒感天空Canvasjs特效
  5. 本地虚拟机搭建k8s集群完整篇
  6. 三星手机上,setOnEditorActionListener软键盘监听回车无效,解决方案
  7. ubuntu wifi bcm4322 安装驱动
  8. CVPR2022-HairCLIP:基于文本和参考图像的头发编辑方法论文理解
  9. 私域运营第五讲:实体店私域流量拉新实体餐饮店如何通过搭建私域流量实现营收增长
  10. 嵌入式设备NFS挂载目录(基于iTop 4412)