• 《springboot源码系列》——自动装配原理


    自动装配原理

      springboot的核心就是自动装配、开箱即用。我们的启动类都加上 @SpringBootApplication 注解,它是个复合注解里面包含了 @EnableAutoConfiguration 、默认开启自动装配。
      他会扫描工程中所依赖 jar 的 spring.factories 配置文件,里面就注册了这个框架的 XXXAutoConfiguration 。每个第三方框架的 XXXAutoConfiguration类都有@Conditional 注解指定他生效的条件,这个条件类似于,比如你有没有引入指定的依赖、有没有给个什么配置、或者某个bean之内的。
      然后如果符合生效的条件,那么此时就会对XXXAutoConfiguration中定义的bean进行实例化、根据你在配置文件中的属性、实例化bean,注入到spring容器中。最后你就可以在项目中用了。

    启动流程

      我们启动 springboot 项目都是通过 SpringApplication.run(Class, args); 来启动的,跟着源码一步步跟进去可以看到是 new SpringApplication(primarySources).run(args)。也就是说可以分为两步:1 创建 SpringApplication ; 2 run 启动。

    创建 SpringApplication

    辅助判断

      上面就是创建 SpringApplication 的核心源码了,我们先看 deduceFromClasspath() 。它里面写死了一些类,然后类路径开始扫描你所有类和依赖jar的类,如果扫到他内置写死的类,就说明你的工程类型是 servlet,Java web 工程,应该作为基于servlet的web应用程序运行,并且应该启动嵌入式servlet web服务器。

     

    初始化第三方jar扩展点

      紧接着,两次调用 getSpringFactoriesInstances() ,去扫描spring 容器的 ApplicationContextIntializer、ApplicationListener 。他们都是接口,可以被 自定义类 或者 依赖jar 去实现,springboot 获取到了他们之后,会先暂存起来。

       这个方法点进去,最终是执行了 SpringFactoriesLoader.loadFactoryNames(type, classLoader)); 可以看到这里印证了我们上面说的扫描所有依赖jar 的 META-INF/spring.factories 所有的配置类。

       最后执行到了最后一行 this.mainApplicationClass = deduceMainApplicationClass(); 来扫描哪个类包含了 main 方法。然后将这个类作为你的启动类!至此,SpringApplication创建完成。

     

    运行run()

      run()点击来,上面几行没啥实际意义,然后扫描实现了 RunListeners 了的类,然后 listeners.starting(); 回调他们的方法。

     

      然后通过 prepareEnvironment() 获取环境配置。

    初始化spring容器

      context = createApplicationContext();
      紧接着,这个方法里面通过 AnnotationConfigServletWebServerApplicationContext 初始化了spring容器。

    准备容器

      接着就执行了 prepareContext(),主要是初步执行第三方jar扩展点,加入spring容器中。其实核心代码就是在 applyInitializers 对扫描第三方框架的AutoConfiguration进行初始化。

    执行的扩展点(自动装配)

      refreshContext()这里就会对 spring容器 进行refresh操作了、执行容器中的所有bean。代码逻辑比较繁琐,我这里直接贴出来调用路径。refreshContext(context); ——> refresh(context); ——> refresh()

    启动内置tomcat

      首先在执行 onRefresh() 的时候,被子类 ServletWebServerApplicationContext 重写了该方法,它里面就是调用了 tomcat 原生的api创建了 webserver并启动。

    初始化bean

     然后继续往下走到了 finishBeanFactoryInitialization(beanFactory);到了这里 beanFactory.preInstantiateSingletons(); 就是springboot的自动装配了。会将所有第三方jar的的bean实例化好、比如redis、mybatis,以及我们自己写的 controller、service 之内的。并注入到spring中去。

  • 相关阅读:
    知识积累
    路由层
    数据表记录的增删改查
    连接数据库
    django数据请求
    力扣(LeetCode) 509. 斐波那契数
    力扣(LeetCode)69. x 的平方根
    力扣(LeetCode) 104. 二叉树的最大深度
    力扣(LeetCode) 27. 移除元素
    力扣(LeetCode) 136. 只出现一次的数字
  • 原文地址:https://www.cnblogs.com/wlwl/p/14966225.html
Copyright © 2020-2023  润新知