0.Springboot概述

官网:https://spring.io/projects/spring-boot

1. Springboot是什么

一个敏捷易用、功能强大、应用广泛的java开发框架

2. 为什么要有Springboot

  1. 需求:开发中我们希望能够简单快速的构建我们的项目,我们希望能更多的关注于我们的业务,而不是繁琐的配置等
  2. 演变:Spring->Springboot->Springcloud等
  3. 实际: Springboot来源于Spring,所以它继承了Spring的两大核心功能(IOC/AOP),然后它通过起步依赖、自动配置等方式,来简化Spring里面繁琐的配置和依赖管理,达到敏捷易用的目的,同时由它催生出以后的Springcloud框架

3. Spring与Springboot开发对比

  1. 使用Spring开发一个web项目
1.创建项目,加入依赖,并解决版本问题
2.配置web配置文件
3.配置Spring配置文件/Spring-mvc配置文件
4.编写代码
5.使用tomcat等部署
  1. 使用Springboot开发一个web项目
1.创建项目,选择依赖
2.编写代码并启动

4. Springboot重要功能的分析(以快速创建的web工程为例,创建过程参见下一篇博客)

1. 起步依赖

在使用ssm框架进行web开发时,我们必须手动添加依赖,不仅需要配置web依赖,还要配置web所需要的周边依赖比如json格式,mvc模型等相关依赖,并且如果导入的依赖之间有版本冲突,我们还需要自己解决这些冲突,而使用springboot你只需要添加一个spring-boot-starter-web依赖不需要写版本号,其余的步骤,springboot都为我们做好了,那springboot是怎么样将web工程所需要的周边依赖加入程序中以及如何处理这些依赖冲突的呢?(1-3说明为什么不需要写版本号及解决冲突,4-5说明为啥不需要写周边依赖)

代码如下(都在pom文件中)

<!--1.首先所有的springboot工程都会有如下的父依赖-->
<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
<!--2.点击进入此父依赖之后,会发现此pom里面会有属性、监听、资源文件路径、开发插件、配置等相关的设置,但是最重要的是spring-boot-starter-parent依然有父依赖spring-boot-dependencies-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.3.3.RELEASE</version>
  </parent>
<!--3.点击进入spring-boot-dependencies之后,会发现此2.3.3.RELEAS版本的pom有<properties>这里面将能相互适用的大多数依赖的版本号都加入了其中,并且在 <dependencyManagement>中排除了一些依赖冲突,这些都适用于2.3.3.RELEAS版本-->
<properties>
    <activemq.version>5.15.13</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.81</appengine-sdk.version>
    <artemis.version>2.12.0</artemis.version>
    <aspectj.version>1.9.6</aspectj.version>
    <assertj.version>3.16.1</assertj.version>
    <atomikos.version>4.0.6</atomikos.version>
    <awaitility.version>4.0.3</awaitility.version>
    <bitronix.version>2.1.4</bitronix.version>
    <build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version>
    <byte-buddy.version>1.10.14</byte-buddy.version>
    <caffeine.version>2.8.5</caffeine.version>
    <cassandra-driver.version>4.6.1</cassandra-driver.version>
    <classmate.version>1.5.1</classmate.version>
    <commons-codec.version>1.14</commons-codec.version>
    <commons-dbcp2.version>2.7.0</commons-dbcp2.version>
    <commons-lang3.version>3.10</commons-lang3.version>
    <commons-pool.version>1.6</commons-pool.version>
    <commons-pool2.version>2.8.1</commons-pool2.version>
    <couchbase-client.version>3.0.7</couchbase-client.version>
    <db2-jdbc.version>11.5.4.0</db2-jdbc.version>
    <dependency-management-plugin.version>1.0.10.RELEASE</dependency-management-plugin.version>
    <derby.version>10.14.2.0</derby.version>
    <dropwizard-metrics.version>4.1.12.1</dropwizard-metrics.version>
    <ehcache.version>2.10.6</ehcache.version>
    <ehcache3.version>3.8.1</ehcache3.version>
    <elasticsearch.version>7.6.2</elasticsearch.version>
    <embedded-mongo.version>2.2.0</embedded-mongo.version>
    <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
    <flatten-maven-plugin.version>1.2.4</flatten-maven-plugin.version>
    
    <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-amqp</artifactId>
        <version>${activemq.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-blueprint</artifactId>
        <version>${activemq.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-broker</artifactId>
        <version>${activemq.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-camel</artifactId>
        <version>${activemq.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-client</artifactId>
        <version>${activemq.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-console</artifactId>
        <version>${activemq.version}</version>
        <exclusions>
          <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
<!--4.以上我们可知spring-boot-dependencies对各个依赖的版本进行了规定,我们回到项目的pom文件,点击我们为web工程加入的-->
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
<!--5.我们会进入spring-boot-starter-web-2.3.3.RELEASE.pom文件(2.3.3跟spring-boot-dependencies同步),在此文件中我们可以看到web-starter依赖如下的周边依赖,此处springboot已经为我们配置好了-->
<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.3.3.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.3.3.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.3.3.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.8.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.8.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

总结如下:我们只需要加入一个web-starter,程序会根据spring-boot-starter-parent的父依赖spring-boot-dependencies的版本找到所有此dependencies版本下规定的web-starter版本,然后在根据此版本的web-starter找到相应的版本的周边依赖starter,并且这些starter已经被spring-boot-dependencies解决过冲突了,
即这些starter都在dependencies的版本的统一管理下,2.3.3.RELEASE的dependencies里面的下的jar包版本相互适用

2. 自动配置

在使用ssm框架进行web开发时,我们解决完依赖之后,下一步就是编写配置文件,如web.xml文件,spring相关配置文件,springmvc相关配置文件,但是用springboot新建这种项目,却不需要配置这些,springboot是如何做到,不必配置这些看起来应该是web工程必须的配置文件的呢?

代码如下

//1.首先我们找到程序的入口
@SpringBootApplication
public class SpringBootWebApplication {

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

}
//2.我们跟踪上面的run方法,到达如下代码,代码含义是将classpath:下的文件读取到程序中作为启动参数,classpath下只有下图所示的三个相关文件,显然只有SpringBootWebApplication涉及自动配置相关内容(yml文件为空,TestController是业务代码并不是必须的),所以我们需要跟踪SpringBootWebApplication的注解
public interface ResourceLoader {
    String CLASSPATH_URL_PREFIX = "classpath:";

    Resource getResource(String var1);

    @Nullable
    ClassLoader getClassLoader();
}

在这里插入图片描述

//跟踪注解@SpringBootApplication到@EnableAutoConfiguration到(@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class))
//3.先来看@AutoConfigurationPackage里面有一个@Import(AutoConfigurationPackages.Registrar.class)
//此类是AutoConfigurationPackages下的内部类,对register进行断点调试,可知此方法是将@SpringBootApplication注解修饰的启动类下的所有文件扫描到容器中
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImports(metadata));
		}

	}

在这里插入图片描述

在这里插入图片描述

//4.再来看@Import(AutoConfigurationImportSelector.class),
//对AutoConfigurationImportSelector进行调试,重要方法为selectImports
@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
//往下走
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		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 = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}
//接着往下走
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//配置类名称由getSpringFactoriesLoaderFactoryClass(),得来,继续跟踪此方法,发现这些配置名都来自于String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
		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;
	}

getSpringFactoriesLoaderFactoryClass()由这个方法从这个文件中取得所有的配置类的名字
在这里插入图片描述

然后根据上面所取得的名字,在autoconfigure的jar包下,将配置类扫描到容器中
在这里插入图片描述
//这个地方是扫描出来的类,这样就完成了自动配置
在这里插入图片描述
总结:autoconfigure的jar包是主要管理springboot自动配置的,里面的META-INF/spring.factories记录了所有需要用到的自动配置类的表单,org.springframework.boot.autoconfigure下是一个个具体的配置类,程序启动会读取表单,按照表单扫描配置类,将它们一个个加入到容器中,这样就不在需要我们进行配置了。

4.补充知识

1.Springboot还有CLI命令行开发模式,以及Actuato监控等更多的功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值