SpringBoot - 基础

1 认识SpringBoot

1.1 介绍

SpringBoot的底层是Spring,SpringBoot是为了解决Spring整合开发过程中配置过于复杂而诞生的,它简化了Spring技术栈的开发,是一个开发Spring技术栈的快速开发的脚手架,也可以说是整合Spring技术栈的一站式框架。

SpringBoot的字面意思就是”Spring的开始”,也就是说,开发和使用Spring技术栈就从SpringBoot开始。

1.2 SpringBoot特性

优点:

  • Create stand-alone Spring applications
    • 创建独立Spring应用
  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
    • 内嵌web服务器(默认是Tomcat,不需要部署成war包了)
  • Provide opinionated ‘starter’ dependencies to simplify your build configuration
    • 通过选择‘started”来简化构建配置
  • Automatically configure Spring and 3rd party libraries whenever possible
    • 自动配置Spring和第三方功能
  • Provide production-ready features such as metrics, health checks, and externalized configuration
    • 提供生成级别的监控、健康检查及外部配置的特性
  • Absolutely no code generation and no requirement for XML configuration
    • 绝对的无代码生成和无需编写xml配置

缺点:

  • 人称版本帝,版本发布频繁。
  • 封装深,内部原理复杂

2 时代背景

2.1 微服务时代

James Lewis and Martin Fowler (2014) 提出微服务完整概念。https://martinfowler.com/microservices/

In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.-- James Lewis and Martin Fowler (2014)

微服务介绍:

微服务是一种架构风格,将一个应用拆分为多个小型服务,每个服务独立运行、部署和升级,服务之间通过轻量级HTTP交互。微服务根据业务拆分,可以由全自动部署机制独立部署。这种架构风格去中心化,每个服务可以使用不同的语言编写。

2.2 分布式

微服务架构涉及到分布式的部署方式。由此带来的困难:

远程调用、服务发现、负载均衡、服务容错、配置管理、服务监控、链路追踪、日志管理、任务调度、…

分布式的解决:

  • SpringBoot + SpringCloud

2.3 云原生

简单理解就是充分利用云优势。原生应用如何上云。 Cloud Native。相对于本地而言的。

实现方式有以下几种。

img

3 第一个SpringBoot

参照官方文档:https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/getting-started.html#getting-started-first-application

3.1 创建POM

使用IDEA创建简单MAVEN项目,增加。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
</parent>

3.2 增加starter依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

3.3 编写代码

入口程序,@SpringBootApplication表示是一个SpringBoot应用。

@SpringBootApplication
public class MainApplication {

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

编写组件:

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String test(){
        return "hello, SpringBoot !";
    }
}

3.4 运行

直接运行main函数,即可在浏览器中访问。

3.5 简化配置

SpringBoot集中管理配置,全在application.properties配置文件中管理,正所谓约定大于配置,配置文件的名字必须是这个。

#配置端口号为8888
server.port=8888

详细配置查看官方文档

3.6 简化部署

可以直接打包成可执行jar包,

在SpringBoot之前,web应用需要打包成war包,在部署到Tomcat中。现在SpringBoot已经可以全部打包到一个jar包中,嵌入了Tomcat服务器,可直接运行。

配置并打包:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-51RAWTV4-1614423715460)(C:\Users\zl\AppData\Roaming\Typora\typora-user-images\image-20210226160357869.png)]

打开cmd运行:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dmuH4EIa-1614423715465)(C:\Users\zl\AppData\Roaming\Typora\typora-user-images\image-20210226160632001.png)]

4 自动装配原理

4.1 依赖管理

父项目的依赖管理

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
</parent>

spring-boot-starter-parent-2.4.3.pom
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.4.3</version>
</parent>

spring-boot-dependencies-2.4.3.pom:这里面包含了几乎所用到的依赖版本号。
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.3</version>

无需版本号,也可以在pom中加入想修改的版本号,如MySQL

<properties>
    <mysql.version>5.1.43</mysql.version>
</properties>

4.2 场景启动器starter

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

针对于常用的Spring使用场景,SpringBoot都定义一个启动器,里面就是写好的依赖。

官方常用的starter都是spring-boot-starter-*的形式,常用starter见官网

4.3 自动配置

  • 自动装配Tomcat

    • spring-boot-dependencies-2.4.3.pom中可以看到加载了Tomcat的依赖。
  • 自动装配SpringMVC

    • 引入SpringMVC全套组件

    • 通过getBeanDefinitionNames可以查看加载的组件,其中就有dispatcherServlet等。

    • String[] beanDefinitionNames = run.getBeanDefinitionNames();
      for (String beanDefinitionName : beanDefinitionNames) {
          System.out.println(beanDefinitionName);
      }
      
  • 自动配置web常用功能

    • 如字符编码characterEncodingFilter
  • 默认的包结构

    • 已经配置了扫描主程序同目录下的所有组件。
    • 官方提供的默认包结构:
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q5ues02M-1614423715468)(C:\Users\zl\AppData\Roaming\Typora\typora-user-images\image-20210226191217563.png)]
  • 各种配置拥有默认值

    • 所有的配置都有默认值,在相对于的properties文件中。
    • 需要修改配置值,就在application.properties中重新配置即可。
  • 按需加载自动配置项

    • 根据应用场景,会按需自动加载该场景下的依赖包。
    • SpringBoot的所有的自动装配功能都在spring-boot-autoconfigure包里。
    • 每个xxxautoConfiguration类都是一个配置类。

5 容器中注解

5.1 @Configuration

  • 放在类上代表该类是个配置类,相当于xml配置文件。
  • 该类也会当做一个组件加入到容器中。
  • 新增了proxyBeanMethods的变量
    • full模式(proxyBeanMethods = true) 内部的bean相当于是单例模式,默认模式
    • Lite模式 (proxyBeanMethods = false) 内部的bean相当于原型模式。
  • @Bean 注解的方法名就是组件ID,返回类型就是组件的类型,返回值就是容器中对象。
@Configuration(proxyBeanMethods=true)
public class UserConfig {

    @Bean
    public User getUser(){
        return new User("Bob", 12);
    }

    @Bean
    public Pet getPet(){
        return new Pet("Tomcat");
    }
}

5.2 @Import

该注解的参数就是class类型,给容器中自动创建class类型的组件,组件ID就是全类限定名。

用法想示例所示

@Import({User.class, Pet.class})

User.class的ID就是com.zl.boot.pojo.User

5.3 @Conditional

条件注解,一般都会是它的子注解,条件注解指定需要满足某些条件,组件才会注入容器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4KvxQGKs-1614423715471)(C:\Users\zl\AppData\Roaming\Typora\typora-user-images\image-20210226205406906.png)]

比如@ConditionalOnBean表示某个对象在容器中存在,才会注入。

@Configuration
public class UserConfig {

    @Bean
    @ConditionalOnBean(name = "Tom") //表示必须有ID为“TOM”的组件,才会将该组件注入到容器。
    public User getUser(){
        return new User("Bob", 12);
    }

    @Bean("Tom")
    public Pet getPet(){
        return new Pet("Tomcat");
    }

}

5.4 @ImportResource

该注解作用就是导入xml配置文件。

比如导入bean.xml配置文件:

@Configuration
@ImportResource("classpath:bean.xml")
public class UserConfig {
    ...
}

5.5 @ConfigurationProperties

将配置文件中的属性值注入到组件中。

有两种用法:

  • @Component + @ConfigurationProperties

    • 组件必须注入,才能将配置文件中的值注入到该组件中

    • @Component
      @ConfigurationProperties(prefix = "mycar")
      public class Car {
          private String brand;
          private int price;
      
          public void setBrand(String brand) {
              this.brand = brand;
          }
      
          public void setPrice(int price) {
              this.price = price;
          }
      }
      
      application.properties文件中
      
      mycar.brand=BM
      mycar.price=10000
      
    • 这样就可以在配置文件配置组件属性的值了。

  • @Configuration + @EnableConfigurationProperties + @ConfigurationProperties

    • 该方法会直接将相应的类型的组件加入到容器中,并配置属性,而无需将Car.class单独注入容器中。

    • @Configuration
      @EnableConfigurationProperties(Car.class)
      public class UserConfig {
      		...
      }
      
      //@Component 不需要手动注入
      @ConfigurationProperties(prefix = "mycar")
      public class Car {
          private String brand;
          private int price;
      
          public void setBrand(String brand) {
              this.brand = brand;
          }
      
          public void setPrice(int price) {
              this.price = price;
          }
      }
      
    • 该方法对于第三方的类很有用。

6 自动配置源码分析

6.1 @SpringBootApplication

@SpringBootApplication注解的结构图:

@SpringBootApplication

  • @SpringBootConfiguration
    • @Configuration – 说明SpringBootApplication也是个配置类
  • @EnableAutoConfiguration
    • @AutoConfigurationPackage
      • @Import({Registrar.class}) – 注入Registrar.class
    • @Import({AutoConfigurationImportSelector.class}) – 注入AutoConfigurationImportSelector.class
  • @ComponentScan – 扫描

从结构中可以看出,@SpringBootApplication是一个配置类,并且导入了两个组件,Registrar.class和AutoConfigurationImportSelector.class。

6.2 为什么SpringBoot自动扫描主程序下的组件

分析Registrar.class

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

    	//metadata注解原信息
        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            //register
            AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }

    }

AnnotationMetadata metadata 是注解原信息,这个注解在入口程序MainApplication上,获得的包名是就是
MainApplication所在的包。

AutoConfigurationPackages.registe将该包名下的组件注入到容器中,这就解释了为什么SpringBoot会自动扫描MainApplication所在目录下的所有组件。

6.3 自动配置类的注入

分析AutoConfigurationImportSelector.class

这个类中的selectImports方法,返回哪些类是需要注入的。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
    ...
        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
    ...
}

重点是这个方法:

getAutoConfigurationEntry(annotationMetadata)

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        ...
            
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        
       ...
    }

这里重要是getCandidateConfigurations获取候选配置方法。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    return configurations;
}

接下来是loadFactoryNames

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    ClassLoader classLoaderToUse = classLoader;
    if (classLoader == null) {
        classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
    }

    String factoryTypeName = factoryType.getName();
    return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

再往里是loadSpringFactories:

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

            try {
                Enumeration urls = classLoader.getResources("META-INF/spring.factories");

                ...
            } catch (IOException var14) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
            }
        }
    }

在这里可以看到: Enumeration urls = classLoader.getResources(“META-INF/spring.factories”);

说明会加载各个依赖包下META-INF/spring.factories这个配置文件。

特别是spring-boot-autoconfigure-2.4.3.jar这个包里面的META-INF/spring.factories配置文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0P4TORlq-1614423715473)(C:\Users\zl\AppData\Roaming\Typora\typora-user-images\image-20210227130919515.png)]

可以看到,其中包含了大量AutoConfiguration结尾的包,这些包都是响应功能的配置类

但是这些配置类里的组件不会全部注入到容器中,而是按需注入,实现的方式是@Conditional注解。

6.4 配置类按需注入

比如AopAutoConfiguration配置类。这个配置类组件会注入容器,但是内部配置类就会根据条件是否注入。

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnProperty(
    prefix = "spring.aop",
    name = {"auto"},
    havingValue = "true",
    matchIfMissing = true
)
public class AopAutoConfiguration {
    ...
    @ConditionalOnClass({Advice.class})
    static class AspectJAutoProxyingConfiguration {
        ...
    }
    
    ...
}

AOP有这个注解@ConditionalOnClass({Advice.class}),代表必须存在org.aspectj.weaver.Advice组件才会在容器中注入AspectJAutoProxyingConfiguration这个配置类。

比如HttpEncodingAutoConfiguration配置类

@Configuration(
    proxyBeanMethods = false
)
@EnableConfigurationProperties({ServerProperties.class})
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;

    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
        return filter;
    }
 ...
}

配置了@EnableConfigurationProperties({ServerProperties.class})注解,即绑定配置文件,在characterEncodingFilter中,使用的配置文件中值。

ServerProperties中有默认值,也会从application.properties中获取值,这样就可用通过配置application.properties文件来改变组件中的配置。

@ConditionalOnMissingBean条件

characterEncodingFilter方法中的这个注解也说明该组件注入时会先判断容器中是否已经存在该组件,存在就不注入。所以,用户可以在自己的配置类中注入characterEncodingFilter组件,就达到了自定义默认组件的功能。

比如用户注入一个bean

@Bean
public CharacterEncodingFilter myFilter(){}

6.5 总结

  • SpringBoot会先加载所有的自动配置类(xxxAutoConfiguration)。 当然,有些自动配置类因为条件过滤而不加载。
  • 每个加载的自动配置类会按需向容器中注入组件,即加入了相应的功能。如dispatcherServlet
  • 自动配置类会默认绑定配置文件,默认配置又会读取application.properties文件中的属性,最后将属性注入到组件中
  • 定制配置的方式
    • 用户配置application.properties
    • 用户自己注入组件

7 SpringBoot的最佳实践

7.1 引入场景依赖

7.2 查看自动配置了哪些

  • 可以分析依赖包spring-boot-autoconfigure-2.4.3.jar
  • 在application.properties中配置debug=true,会打印出(注入组件)Positive matches和(未注入组件)Negative matches

7.3 修改配置

  • 在application.properties配置,配置项查看官网

  • 可以分析自动配置类@EnableConfigurationProperties注解的xxxproperties类。

  • 在自己的配置类中注入组件覆盖SpringBoot底层的默认组件

  • 自定义器 XXXXXCustomizer

以上做完,就是开始编写自己的业务代码了。

8 开发小技巧

8.1 Lombok

自动添加get、set、构造等方法。适用于pojo类。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private int age;
    private Pet pet;
}

8.2 log4j

使用注解可以快速引入日志打印

import lombok.extern.log4j.Log4j2;

@Configuration
@Log4j2
public class UserConfig {

    @Bean
    public User getUser(Pet pet){
        User bob = new User();
        log.info("create new User"); //直接使用
        return bob;
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EIN3rJcD-1614423715474)(C:\Users\zl\AppData\Roaming\Typora\typora-user-images\image-20210227184028834.png)]

8.3 dev-tools

官方提供的类似于热重启的开发者工具,比如在开发web中,就不需要重启整个web应用了。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

IDEA中修改代码之后,点击Build —> Build Project ,快捷键Ctrl + F9

8.4 Spring Initialize

在IDEA中创建新项目时,可以使用Spring Initialize(项目创建向导)进行创建。如下图,可以勾选自己想要支持的业务功能。会自动编写pom文件及一些目录的创建。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bzMve46p-1614423715475)(C:\Users\zl\AppData\Roaming\Typora\typora-user-images\image-20210227185515977.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: idea-springboot-projectes是指使用IDEA开发工具构建Spring Boot项目的过程。Spring Boot是一个流行的开源框架,可以帮助Java开发者快速构建高效的微服务应用。IDEA则是一个以Java基础的集成开发环境,可以提供代码编辑、调试、测试和部署等功能。 在构建Spring Boot项目时,IDEA可以通过自带的Spring Initializr工具或者通过手动配置的方式来进行。Spring Initializr可以自动生成项目基础框架,包括依赖库、项目结构、POM文件等。而手动配置则需要开发者自行添加所需要的依赖库和配置文件。 在项目开发过程中,IDEA可以提供强大的代码提示和自动补全功能,包括快捷键、代码重构、调试等。此外,IDEA还支持各种测试框架和部署方式,方便开发者快速进行测试和部署。 总的来说,使用IDEA开发Spring Boot项目可以提高开发效率和代码质量,并且可以使用各种插件和扩展来增强开发体验。这是一个非常流行的Java开发模式,适用于各种类型的应用程序和系统。 ### 回答2: Idea-SpringBoot-Project是一个使用了Spring Boot框架的项目,有助于Java开发者轻松构建Web应用程序。Spring Boot是一个流行的Java框架,它可以帮助开发者更快地构建更好的应用程序。使用Idea-SpringBoot-Project,开发者可以轻松创建具有高可用性和可扩展性的Java Web应用程序。 Idea-SpringBoot-Project引入了许多方便的功能,如Spring容器管理、数据访问和Web MVC框架等。通过使用Spring Boot,开发者可以在不需要手动配置的情况下快速构建应用程序。而使用Idea作为开发工具,则能帮助开发者更快地编写代码和进行调试。这个项目不仅可以在Windows和Linux平台上运行,还与许多其他大型Java库和框架兼容,如Spring Security和Hibernate等。 总之,Idea-SpringBoot-Project帮助开发者将更多的时间专注于应用程序逻辑和功能,而不是花费时间和精力去手动配置。通过这个项目,开发者可以构建出高性能、高度可用性和可扩展性的Java应用程序。 ### 回答3: idea-springboot-projectes是针对Spring Boot框架的项目管理功能的开发工具集成环境。它提供了一种方便快捷的方式来创建、维护和调试Spring Boot项目。 idea-springboot-projectes使开发人员能够在一个单一的界面中,管理不同的Spring Boot项目,包括应用程序、库和插件。它自动生成项目结构,提供依赖管理,支持代码重构、调试和测试等功能,同时也能够整合其他常用开发工具如Maven、Gradle等,进一步提升开发效率。 通过idea-springboot-projectes,开发人员可以快速创建Spring Boot应用程序。一旦项目创建完成,可以通过IDEA的自动配置机制,无需编写大量的代码即可完成基础设施的搭建和配置。同时,IDEA也提供了许多Spring Boot Starter库,这些库包含了大量常用的功能和组件,帮助开发人员轻松实现各种业务需求。 总之,idea-springboot-projectes是一款非常实用的开发工具,为Spring Boot开发提供了强大的项目管理和开发支持,同时提高了开发效率和代码质量,使得开发人员能够更专注于业务代码的编写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值