0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

深度盘点一遍自动装配原理(上)

jf_78858299 来源:Java知音 作者: Object 2023-04-07 11:18 次阅读

前言

Spring翻译为中文是“春天”,的确,在某段时间内,它给Java开发人员带来过春天,但是随着我们项目规模的扩大,Spring需要配置的地方就越来越多,夸张点说,“配置两小时,Coding五分钟”。这种纷繁复杂的xml配置随着软件行业一步步地发展,必将逐步退出历史舞台。


SpringBoot介绍

来自:百度百科

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

SpringBoot所具备的特征有:

  • 可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
  • 内嵌Tomcat或Jetty等Servlet容器;
  • 提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
  • 尽可能自动配置Spring容器;
  • 提供准备好的特性,如指标、健康检查和外部化配置;
  • 绝对没有代码生成,不需要XML配置。

自己的理解:

SpringBoot,顾名思义,给人的感觉就是让Spring启动的这么一个项目。在过去,我们要让一个Spring项目启动,往往需要配置很多的xml配置文件,但是在使用SpringBoot之后,我们甚至无需写一行xml,就可以直接将整个项目启动,这种“零配置”的做法减轻了开发人员很多的工作量,可以让开发人员一心扑在业务逻辑的设计上,使项目的逻辑更加完善。

除此之外,其采用了JavaConfig的配置风格,导入组件的方式也由原来的直接配置改为@EnableXXXX,这种纯Java代码的配置和导入组件的方式,使代码看上去更加的优雅,所以SpringBoot如今受到大小公司和大多数程序员的青睐,不是没有原因的。

SpringBoot之所以可以做到简化配置文件直接启动,无外乎是其内部的两种设计策略: 开箱即用和约定大于配置

开箱即用:在开发过程中,通过maven项目的pom文件中添加相关依赖包,然后通过相应的注解来代替繁琐的XML配置以管理对象的生命周期。

约定大于配置:由SpringBoot本身来配置目标结构,由开发者在结构中添加信息的软件设计范式。这一特点虽降低了部分灵活性,增加了BUG定位的复杂性,但减少了开发人员需要做出决定的数量,同时减少了大量的XML配置,并且可以将代码编译、测试和打包等工作自动化。

那么在这篇博客中,我们需要了解的所有东西,就应该从这两个特点出发,一步一步深入SpringBoot自动装配的原理。


开箱即用原理

要理解这一特点,首先要先自己体会开箱即用的整个过程带来的便利。

体验开箱即用

SpringBoot提供了我们快速创建SpringBoot项目的地方:https://start.spring.io/

我们只需要在这个网页中把整个项目起好名字,然后选好我们需要的组件,就可以直接获得一个可以跑起来的SpringBoot项目。

图片

我们只需要填完上述信息,点击Generate,就可以直接将一个SpringBoot项目下载下来,然后导入我们的IDE,Eclipse或者IDEA都可,之后就可以直接将它运行起来。

全项目结构:

图片

启动:

图片

访问:http://localhost:8080/

图片

代表整个SpringBoot项目启动成功。

开箱即用原理剖析

对比SSM配置

其实在上文的开箱即用中,我们相当于引入了一个SpringMVC的组件,但是大家可以看到,我们没有经过任何的配置就将项目启动了。反观过去SSM框架的SpringMVC配置,我这里有一份留存的大家可以对比一下。

spring-web.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
    
    
    
    <mvc:annotation-driven />

    
    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:default-servlet-handler />

    
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/html/"><span class="hljs-name"property>
        <property name="suffix" value=".html"><span class="hljs-name"property>
    <span class="hljs-name"bean>
    
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"><span class="hljs-name"property>
        <property name="maxUploadSize" value="10485760000"><span class="hljs-name"property>
        <property name="maxInMemorySize" value="20971520"><span class="hljs-name"property>
    <span class="hljs-name"bean>
    
    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean
                    class="org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html;charset=UTF-8<span class="hljs-name"value>
                        <span class="hljs-name"list>
                    <span class="hljs-name"property>
                <span class="hljs-name"bean>
            <span class="hljs-name"list>
        <span class="hljs-name"property>
    <span class="hljs-name"bean>
    
    <context:component-scan base-package="com.SchoolShop.o2o.web" />
    
<span class="hljs-name"beans>

web.xml:


      name>spring-dispatcherclass="hljs-name"servlet-name>
      class>org.springframework.web.servlet.DispatcherServletclass="hljs-name"servlet-class>
      
          name>contextConfigLocationclass="hljs-name"param-name>
          value>classpath:spring/spring-*.xmlclass="hljs-name"param-value>
      class="hljs-name"init-param>
  class="hljs-name"servlet>
  mapping>
      name>spring-dispatcherclass="hljs-name"servlet-name>
      
      /class="hljs-name"url-pattern>
  class="hljs-name"servlet-mapping>

可以看到,这里需要配置两个文件,web.xml和spring-web.xml,配置可以说是相当繁重。

那么相对于这个,SpringBoot的开箱即用就显得特别方便,那么我们着重聊聊SpringBoot开箱即用的原理。

从pom.xml开始

SpringBoot的项目都会存在一个父依赖,按住Ctrl+鼠标左键,可以点进去。

<parent>
    <groupId>org.springframework.boot<span class="hljs-name"groupId>
    <artifactId>spring-boot-starter-parent<span class="hljs-name"artifactId>
    <version>2.2.1.RELEASE<span class="hljs-name"version>
    <relativePath/> 
<span class="hljs-name"parent>

点进去之后发现里面除了一些插件和配置文件的格式之外,还存在一个依赖。

<parent>
    <groupId>org.springframework.boot<span class="hljs-name"groupId>
    <artifactId>spring-boot-dependencies<span class="hljs-name"artifactId>
    <version>2.2.1.RELEASE<span class="hljs-name"version>
    <relativePath>../../spring-boot-dependencies<span class="hljs-name"relativePath>
<span class="hljs-name"parent>

于是再点进去,可以发现里面放了很多的依赖和依赖的版本号。由于这个文件实在太长了,所以这里只展示一部分。

图片

图片

所以我们可以得出第一个结论:

spring-boot-dependencies:作为父工程,存放了SpringBoot的核心依赖。我们在写或者引入一些SpringBoot依赖的时候,不需要指定版本,正是因为SpringBoot的父依赖已经帮我们维护了一套版本。

另外我们还可以看到,在父依赖中也帮我们写好了资源库,不用我们自己再去配置了。


      
        trueclass="hljs-name"filtering>
        ${basedir}/src/main/resourcesclass="hljs-name"directory>
        <includes>
            
          <include>**/application*.ymlclass="hljs-name"include>
          <include>**/application*.yamlclass="hljs-name"include>
          <include>**/application*.propertiesclass="hljs-name"include>
        class="hljs-name"includes>
      class="hljs-name"resource>
      
        ${basedir}/src/main/resourcesclass="hljs-name"directory>
        
          <exclude>**/application*.ymlclass="hljs-name"exclude>
          <exclude>**/application*.yamlclass="hljs-name"exclude>
          <exclude>**/application*.propertiesclass="hljs-name"exclude>
        class="hljs-name"excludes>
      class="hljs-name"resource>
class="hljs-name"resources>

启动器

<dependency>
    <groupId>org.springframework.boot<span class="hljs-name"groupId>
    <artifactId>spring-boot-starter<span class="hljs-name"artifactId>
    <version>2.2.1.RELEASE<span class="hljs-name"version>
<span class="hljs-name"dependency>

启动器就是SpringBoot的启动场景,比如我们要使用web相关的,那么就直接引入spring-boor-starter-web,那么他就会帮我们自动导入web环境下所有必需的依赖。

我们来看看启动器中存放了一些什么内容:

以spring-boot-starter为例:

<dependency>
      <groupId>org.springframework.boot<span class="hljs-name"groupId>
      <artifactId>spring-boot<span class="hljs-name"artifactId>
      <version>2.2.1.RELEASE<span class="hljs-name"version>
      <scope>compile<span class="hljs-name"scope>
    <span class="hljs-name"dependency>
    <dependency>
      <groupId>org.springframework.boot<span class="hljs-name"groupId>
      <artifactId>spring-boot-autoconfigure<span class="hljs-name"artifactId>
      <version>2.2.1.RELEASE<span class="hljs-name"version>
      <scope>compile<span class="hljs-name"scope>
    <span class="hljs-name"dependency>
    <dependency>
      <groupId>org.springframework.boot<span class="hljs-name"groupId>
      <artifactId>spring-boot-starter-logging<span class="hljs-name"artifactId>
      <version>2.2.1.RELEASE<span class="hljs-name"version>
      <scope>compile<span class="hljs-name"scope>
    <span class="hljs-name"dependency>
    <dependency>
      <groupId>jakarta.annotation<span class="hljs-name"groupId>
      <artifactId>jakarta.annotation-api<span class="hljs-name"artifactId>
      <version>1.3.5<span class="hljs-name"version>
      <scope>compile<span class="hljs-name"scope>
    <span class="hljs-name"dependency>
    <dependency>
      <groupId>org.springframework<span class="hljs-name"groupId>
      <artifactId>spring-core<span class="hljs-name"artifactId>
      <version>5.2.1.RELEASE<span class="hljs-name"version>
      <scope>compile<span class="hljs-name"scope>
    <span class="hljs-name"dependency>
    <dependency>
      <groupId>org.yaml<span class="hljs-name"groupId>
      <artifactId>snakeyaml<span class="hljs-name"artifactId>
      <version>1.25<span class="hljs-name"version>
      <scope>runtime<span class="hljs-name"scope>
    <span class="hljs-name"dependency>

其中存放了自动配置相关的依赖、日志相关依赖、还有Spring-core等依赖,这些依赖我们只需要导入一个spring-boor-starter就可以直接将其全部引入,而不需要再像以前那样逐个导入了。

SpringBoot会将所有的功能场景都封装成一个一个的启动器,供开发人员使用。

我们在使用的时候也可以直接去官网上找我们所需的启动器,直接将其引入。

获取启动器文档:

https://docs.spring.io/spring-boot/docs/2.2.1.RELEASE/reference/html/using-spring-boot.html#using-boot-starter

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2964

    浏览量

    104689
  • 开发
    +关注

    关注

    0

    文章

    370

    浏览量

    40836
  • 框架
    +关注

    关注

    0

    文章

    403

    浏览量

    17471
  • spring
    +关注

    关注

    0

    文章

    340

    浏览量

    14334
收藏 人收藏

    评论

    相关推荐

    ESP32用的开发版尝试smartconfig,功能使用正常,但是只要重启后又要设置一遍,怎么才能记住配置?

    用的开发版尝试smartconfig,功能使用正常,但是只要重启后又要设置一遍 怎么才能记住配置?
    发表于 06-26 07:13

    [转帖]当你扛不住的时候就读一遍

      当你扛不住的时候就读一遍1.不求与人相比,但求超越自己,要哭就哭出激动的泪水,要笑就笑出成长的性格。  2.与其用泪水悔恨今天,不如用汗水拼. 搏今天。  3.当眼泪流尽的时候
    发表于 05-24 11:58

    个人认为51汇编至少过一遍

    个人认为51汇编至少过一遍。现在网上百分之九十的单片机资料都是C 语言的,都适合初学者入门,我觉得这个不错的。现在也越来越多的发烧友认为没必要再学汇编,直接学C语言,这当然没错,可惜,如果你连单片机
    发表于 08-21 08:22

    主程序执行一遍后单片机锁存器怎么变化?

    例如点亮数码管的程序最后行死循环去掉的话锁存器是保持状态使数码管亮着还是执行一遍主函数就灭了?#include***it dula=P2^6;***it wela=P2^7;void main
    发表于 10-19 18:25

    刚学STM32,按照个网上找的LED程序,自己写了一遍,可是...

    刚学STM32,按照个网上找的LED程序,自己写了一遍,可是无法编译!!求大神帮忙解决下,感激不尽。下面是我写的程序。
    发表于 11-04 02:33

    只是为了积分,刷一遍主题

    只是为了积分,刷一遍主题
    发表于 10-11 11:14

    已经跟着入门书籍学了一遍LabVIEW基础知识,现在该怎么练手呢

    小白刚起步,过了一遍基本知识后不知如何开展下步,大神们给指导个方向,或者下步需要用的学习资料也可以
    发表于 05-04 16:30

    IAP15W413AS灌程序要先用串口烧录一遍

    IAP15W413AS灌程序要先用串口烧录一遍然后在烧录软件中选择下次用485烧录,为何不能直接用485工具烧录?是啥原因啊!!!
    发表于 06-26 18:35

    6678点击ccml文件debug时当前的out文件会给所有的core都下载一遍

    我的板子是EVM6678L的开发板,ccs5.3版本,现在有个问题,我开始还好好的,突然在次右键点击ccml文件debug时,当前的out文件会给所有的core都下载一遍,在debug之前,我已经选择了只是用core0了,不知道为什么?望达人解答
    发表于 12-28 11:01

    怎么让液晶把每种颜色都显示一遍

    原子哥哥,我想让液晶吧每种颜色都显示一遍,可是有很多种颜色为显示出来?#头文件int main( void ){u16i ; 初始化; do {LCD_Clear( i );i++;delay_ms
    发表于 03-04 06:35

    请问在bootloader里面已经包含的配置在app里面还需要在配置一遍吗?

    请问大家在bootloader里面已经包含的配置在app里面还需要在配置一遍么。。如果在app里面的配置和bootloader里面不样呢。。望高手给予帮助。。
    发表于 04-22 03:26

    为什么任哲VC的移植我只能运行一遍

    只显示一遍MY,不是循环显示。例12-2
    发表于 11-04 03:47

    英伟达AI机器人开发新技能 看一遍就能自学成才

    AI和机器学习已经流行了很久,但我们通常需要输入海量的学习样本和已知结果来让机器学习项新技能。英伟达的研究者为工业机器人开发了种新的学习方法,和我们人类样,机器人能通过观看其他人的操作直接进行模仿,教
    发表于 05-23 02:25 1910次阅读

    深度学习模型能完成几项NLP任务?

    对于机器翻译、文本摘要、Q&A、文本分类等自然语言处理任务来说,深度学习的出现一遍刷新了state-of-the-art的模型性能记录,给研究带来诸多惊喜。但这些任务般都有各自的度
    的头像 发表于 06-26 15:19 4595次阅读

    深度盘点一遍自动装配原理(下)

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
    的头像 发表于 04-07 11:18 416次阅读
    <b class='flag-5'>深度</b><b class='flag-5'>盘点</b><b class='flag-5'>一遍</b><b class='flag-5'>自动</b><b class='flag-5'>装配</b>原理(下)