SpringBoot自动装配原理(简单易懂)

SpringBoot自动装配原理(简单易懂)1、什么是自动装配自动装配就是把别人(官方)写好的config配置类加载到spring容器,然后根据这个配置类生成一些项目需要的bean对象。(小声逼逼:就像我们自己在项目了写的config配置类一样的,只不过这个是别人写好的,你什么都不用管)2、自动装配的开关在哪里@SpringBootApplication|–@EnableAutoConfiguration|–@Import({AutoConfigurationImportSelector.class})在@Spri

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

1、什么是自动装配

自动装配就是把别人(官方)写好的config配置类加载到spring容器,然后根据这个配置类生成一些项目需要的bean对象。
(小声逼逼:就像我们自己在项目了写的config配置类一样的,只不过这个是别人写好的,你什么都不用管)

2、自动装配的开关在哪里

@SpringBootApplication
   |--@EnableAutoConfiguration
     |--@Import({ 
   AutoConfigurationImportSelector.class})

Jetbrains全家桶1年46,售后保障稳定

@SpringBootApplication注解里的@EnableAutoConfiguration@Import注解导入了一AutoConfigurationImportSelector.class类,这个类的selectImports方法会扫描我们类路径下的一个spring.factories文件(里面装的是很多官方写好的自动配置类的全限定名),然后返回这些类的名字。

  • selectImports方法如下:
public String[] selectImports(AnnotationMetadata annotationMetadata) { 
   
        if (!this.isEnabled(annotationMetadata)) { 
   
            return NO_IMPORTS;
        } else { 
   
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }
  • spring.factories文件的位置如下:
    在这里插入图片描述
  • spring.factories文件的内容如下:
    在这里插入图片描述

3、自动装配开始(以tomcat为例)

前面的selectImports函数会拿到 spring.factories文件里的自动配置类,然后去解析这些配置类,这里以ServletWebServerFactoryAutoConfiguration为例
在这里插入图片描述在这里插入图片描述这个类上面有很多条件注解,大致就是说当你的应用是web应用,符合spring MVC那一套,像什么Servlet啊等等,这个配置类才生效。其中这个配置类又用@Import注解导入了几个类如下:

@Import({ 
   ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
 EmbeddedTomcat.class, 
 EmbeddedJetty.class, 
 EmbeddedUndertow.class})

这几个看名字就知道是什么,就是一些web容器嘛,Tomcat、Jetty、Undertow。其实EmbeddedTomcat.classEmbeddedJetty.classEmbeddedUndertow.classServletWebServerFactoryConfiguration里的三个静态内部类。
这里以EmbeddedTomcat.class这个内部类为例,代码如下:

 @ConditionalOnClass({ 
   Servlet.class, Tomcat.class, UpgradeProtocol.class})
    @ConditionalOnMissingBean(
        value = { 
   ServletWebServerFactory.class},
        search = SearchStrategy.CURRENT
    )
    static class EmbeddedTomcat { 
   
        EmbeddedTomcat() { 
   
        }

        @Bean
        TomcatServletWebServerFactory tomcatServletWebServerFactory(ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers, ObjectProvider<TomcatContextCustomizer> contextCustomizers, ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) { 
   
            TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
            factory.getTomcatConnectorCustomizers().addAll((Collection)connectorCustomizers.orderedStream().collect(Collectors.toList()));
            factory.getTomcatContextCustomizers().addAll((Collection)contextCustomizers.orderedStream().collect(Collectors.toList()));
            factory.getTomcatProtocolHandlerCustomizers().addAll((Collection)protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
            return factory;
        }
    }

注意:第一行的 @ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class}),这个条件注解表示你的类路径下有tomcat的依赖,即导入了Tomcat的jar包才会生效,EmbeddedTomcat.classEmbeddedJetty.class也同理,但是只能有一个哈,导入了tomcat的jar包就不能导入其它的,不然会报错,当然了springboot默认tomcat,不需要我们导入。
这里会返回一个TomcatServletWebServerFactory 类,点进去后,其代码如下:

public class TomcatServletWebServerFactory 
extends AbstractServletWebServerFactory 
implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware { 
   
    其它代码不重要,哈哈。。。

这里继承了一个AbstractServletWebServerFactory 类, --------------AbstractServletWebServerFactory 类又继承了--------------AbstractConfigurableWebServerFactory
好,点击AbstractConfigurableWebServerFactory进去就可以看到我们熟悉的8080端口号了,如下:
在这里插入图片描述

3、结束语

其实springboot的自动装配还是比较复杂的,大概可以概括为:在启动类的run方法传入启动类的class(方便后面获取其注解信息)。
执行run方法,创建SpringApplication对象,并用LoadSpringFactories()方法将/META-INF/spring.factories文件里的k-v读入缓存(方便后面加载时使用)。
然后继续run方法,在某处会获取传入的启动类的class,并解析上面的注解,当解析到@Import({AutoConfigurationImportSelector.class})时会将AutoConfigurationImportSelector加载进方法区,通过反射创建对象,调用其某一个方法,从缓存读取前面存储的k-v,并经过一系列的过滤、去重等,最后将需要的配置类加载,生成BD对象,创建Bean对象,放入spring容器。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/234599.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Python 字母大小写的转换

    Python 字母大小写的转换1name="AdaLovelace"2print(name.upper())3print(name.lower())

    2022年7月6日
    22
  • textmate快捷键 汇总

    textmate快捷键 汇总TextMate列编辑模式按住Alt键,用鼠标选择要插入字符的行。如果仅仅是插入字符,注意选择0列-选择多列的话会把它们覆盖掉。选择完毕应该是看到一条细细的竖线,然后输入要插入的字符。TextMate会实时显示所有的更改,很直观,这是TextMate比VIM好的地方。如果只是在许多行前插入空格,则可以选中这些行,使用快捷键Cmd+]增加缩进,在Text…

    2022年7月26日
    8
  • 单据保存后的存储过程称为_原始单据保存多少年

    单据保存后的存储过程称为_原始单据保存多少年(一)报关单证保存后的存储过程更新T_modulelist的StorageProductAfterSave值UPDATET_ModuleListSETStorageProductAfterSave=‘SaveInvoiceAfter’wheremodulename=‘报关单证’2.创建存储过程CREATEPROCSaveInvoiceAfter(@InvoiceNumvarchar(30))AsBegin…写你的逻辑,其中参数@InvoiceNum是单据号end(二)出

    2022年9月21日
    2
  • 菜鸟的数学建模之路(一):最短路径算法「建议收藏」

    菜鸟的数学建模之路(一):最短路径算法「建议收藏」最短路径算法主要有两种,Dijkstra算法和floyd算法,当时在学习这两种算法时经常弄混了,关于这两种算法,记得当时是在交警平台设置的那一道题目上了解到的,就去查很多资料,花了不少时间才基本了解了这两种算法的基本用法,在总结的时候,我更多的是用代码的方式去做的总结,当时想的是等到要用的时候,直接改一下数据,运行代码,得到想要的最短路径就可以了。记得我们老师说过数学建模的知识没必要过于深入的去学…

    2022年6月4日
    157
  • 集合转成数组的方法_数组转化为集合

    集合转成数组的方法_数组转化为集合1.转换方法1.遍历的方式,依次添加到集合中。2.Arrays.asList()方法3.List.of()方法4.Collections.addAll(集合,数组)方法,将集合存储到数组中1.1遍历的方式这种方式转换成的集合,集合长度可变,可以后续向集合添加数据int[]i={1,5,8,7,11,52};//1.遍历的方式Listlist=newArrayList();for(intx:i){

    2022年9月19日
    1
  • 集成灶功能图标解释_为什么不建议买集成灶

    集成灶功能图标解释_为什么不建议买集成灶GitLab Auto DevOps功能与Kubernetes集成教程

    2022年4月22日
    68

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号