SpringBoot 教程基础入门-概述+底层注解

1.Spring 与 SpringBoot

1.1 Spring 能做什么

Spring 官网

SpringBoot 教程基础入门-概述+底层注解_第1张图片

 1.2 Spring 的生态

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

它覆盖了:

  • web 开发
  • 数据访问
  • 安全控制
  • 分布式
  • 消息服务
  • 移动开发
  • 批处理
  • ...

1.3 Spring5 重大升级

1.3.1 响应式编程

SpringBoot 教程基础入门-概述+底层注解_第2张图片

1.3.2 内部源码设计

基于 Java8 的一些新特性,如:接口默认实现。重新设计源码架构。

2.为什么用 Springboot

能够快速创建出生产级别的 Spring 应用。

2.1 SpringBoot 优点

  • 创建独立 Spring 应用
  • 内嵌 web 服务器
  • 自动 starter 依赖,简化构建配置
  • 自动配置 Spring 以及第三方功能
  • 提供生产级别的监控、健康检查及外部化配置
  • 无代码生成、无须编写 XML

SpringBoot 是整合 Spring 技术栈的一站式框架

SpringBoot 是简化 Spring 技术栈的快速开发脚手架

2.2 SpringBoot 缺点

  • 人称版本帝,迭代快,需要时刻关注变化
  • 封装太深,内部原理复杂,不同意精通

3.时代背景

3.1 微服务

  • 微服务是一种架构风格
  • 一个应用拆分为一组小型服务
  • 每个服务运行在自己的进程内,也就是可独立部署和升级
  • 服务之间使用轻量级的 HTTP 交互
  • 服务围绕业务功能拆分
  • 可以由全自动部署机独立部署
  • 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术

3.2 分布式

3.2.1 分布式的困难

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

3.2.2 分布式的解决

SpringBoot + SpringCloud

SpringBoot 教程基础入门-概述+底层注解_第3张图片

3.3 云原生

原生应用如何上云。 Cloud Native

3.3.1 上云的困难

  • 服务自愈
  • 弹性伸缩
  • 服务隔离
  • 自动化部署
  • 灰度发布:新版慢慢覆盖老版本
  • 流量治理
  • ...

3.3.2 上云的解决

  • 初始云原生
  • 深入 Docker-容器化技术
  • 掌握星际级容器编排 Kubernetes
  • DevOps-实战企业 CI/CD,构建企业云平台
  • 拥抱新一代架构 Service Mesh 与 Servletless
  • 云上架与场景方案实战

4 如何学习 SpringBoot

4.1 官方文档架构

文档链接

SpringBoot 教程基础入门-概述+底层注解_第4张图片

5. SpringBoot2 入门

5.1 系统要求

  • Java 8
  • Maven 3.3+

Maven 的配置如下( MAVEN_HOME/conf/settings.xml)


	
		nexus-aliyun
		central
		Nexus aliyun
		http://maven.aliyun.com/nexus/content/groups/public
	



	
		jdk-1.8

		
			true
			1.8
		

		
			1.8
			1.8
			1.8
		
	

5.2 HelloWorld

需求:浏览器发送 /hello 请求,响应 “Hello,SpringBoot 2” 

1)创建 maven 工程

打开 Intellij idea

File --> New -> Project -->Maven(如下图)-->填入项目信息-->Finish

SpringBoot 教程基础入门-概述+底层注解_第5张图片

2)引入依赖



    4.0.0

    org.example
    boot-01-HelloWorld
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.3
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
    

3)创建主程序

/**
 * 主程序类
 * @SpringBootApplication:这是一个 SpringBoot 应用
 */
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class,args);
    }
}

4)编写业务

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public  String handle01() {
        return "Hello,  SpringBoot 2";
    }
}

5)测试

  • 运行 MainApplication 类
  • 浏览器输入   “http://localhost:8080/hello” ,将会输出 “Hello, SpringBoot 2”

6)简化配置

在工程的 resources 文件夹中创建 application.properties 文件。以下为内容

更多配置信息,查看官方文档:链接 

7)简化部署

在 pom.xml 添加


	
		
			org.springframework.boot
			spring-boot-maven-plugin
		
	

在 IDEA 的 Maven 插件上点击运行 clean、package,把 工程打包成 jar 包。 

SpringBoot 教程基础入门-概述+底层注解_第6张图片

打包好的 jar 包被生成在 HelloWorld 工程项目的 target 文件夹内。

用 cmd 运行 

java -jar xxx.jar

将 jar 包直接在目标服务器执行即可。 

6.SpringBoot-依赖管理特性

6.1 依赖管理

1)依赖关系

依赖关系:

POM 文件 --> spring-boot-stater-parent-x.x.x.pom --> spring-boot-dependencies-2.5.3.pom

在我们的 POM 文件中,使用了父项目依赖管理,如下图

SpringBoot 教程基础入门-概述+底层注解_第7张图片

我们按住【ctrl】点击查看 ,发现它的父依赖是 spring-boot-stater-parent-2.5.3.pom

SpringBoot 教程基础入门-概述+底层注解_第8张图片

再次点击进入 spring-boot-stater-parent-2.5.3.pom 的父依赖,为 spring-boot-dependencies-2.5.3.pom。

 spring-boot-dependencies-x.x.x.pom 几乎声明了所有开发中常用的依赖的版本号(自动版本仲裁机制)

SpringBoot 教程基础入门-概述+底层注解_第9张图片

2)导入 starter 场景启动器

我们见到 POM 文件中有很多 【spring-boot-starter-*】,它表示某种场景。只要引入 【spring-boot-starter-*】,这个场景所需的常规的依赖都自动引入。

  • 第三方开发的场景启动器 格式为 【*-spring-boot-starter】
  • SpringBoot 官方列出的所有场景链接

另外所有场景启动器最底层的依赖为【spring-boot-stater】,如下图

SpringBoot 教程基础入门-概述+底层注解_第10张图片

3)无需关注版本号,自动版本仲裁 

  • 引入的依赖默认都可以不写版本。
  •  引入非仲裁的 jar,需要写版本号。

例,要使用mysql驱动,则如下图,注意无需声明版本号

SpringBoot 教程基础入门-概述+底层注解_第11张图片

4)可修改默认的版本号

  1. 查看  spring-boot-dependencies-x.x.x.pom 里面规定的版本 用的 key
  2. 在当前项目里面的 POM 文件重写配置,如下
    
        5.1.43
    

6.2 自动配置

自动配置好 Tomcat

【spring-boot-starter-web】自动引入了 Tomcat 依赖,如下图

SpringBoot 教程基础入门-概述+底层注解_第12张图片

自动配置 Tomcat

自动配置好 SpringMVC

【spring-boot-starter-web】自动引入了 SpringMVC全套组件

SpringBoot 教程基础入门-概述+底层注解_第13张图片

自动配好 SpringMVC 常用组件 

自动配置好 Web 常见功能,如:字符编码问题

SpringBoot 帮我们配置好了所有 Web 开发的常见依赖,如下代码可以查看:

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class,args);
        // 查看容器里面的组件
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }
}

默认的包结构

  • 主程序所在的包,及其所有的子包里面的组件都会被默认扫描进来

如下图:HelloController被扫描进来,而WorldController 未被扫描。

SpringBoot 教程基础入门-概述+底层注解_第14张图片

  • 无须以前的包扫描配置
  • 想要改变扫描路径,有以下两种方式
//第一种方式
@SpringBootApplication(scanBasePackages = "com.out")

//第二种方式 (等同于第一种方式)
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.out")

各种配置拥有默认值

  • 默认配置都是映射到某个类上,如:MultipartProperties
  • 配置文件的值最终会绑定到某个类上,这个类会在容器中创建对象

按需加载所有自动配置项

  • SpringBoot 有非常多的 starter,但是并不是全部都引入的。
  • 只有我们在 POM 文件中引入了哪些 starter,SpringBoot 才会自动配置。
  • SpringBoot 所有的自动配置功能都在 【spring-boot-starter-x.x.x.pom】的 spring-boot-autoconfigure 包里面。

SpringBoot 教程基础入门-概述+底层注解_第15张图片

7.底层注解 - @Configuration 详解

两个实体类

public class Person {
    private String name;
    private int age;
    private Pet pet;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public void setPet(Pet pet) {
        this.pet = pet;
    }

    public Pet getPet() {
        return pet;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}


public class Pet {
    private String name;

    public Pet() {
    }

    public Pet(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

配置类,SpringBoot 启动时会自动加载 @Configuration 下的组件,类似于 Spring 的 xml 配置文件。

/**
 * 1.配置类里面是有 @Bean 标注在方法上给容器注册组件,默认也是单实例的
 * 2.配置类本身也是组件
 * 3.proxyBeanMethods:代理 bean 的方法
 *      proxyBeanMethods=true(Full模式),它是默认值,保证 @Bean 方法被调用前总是会去容器中查看是否有该组件
 *      proxyBeanMethods=false(Lite 轻量级模式),@Bean 方法直接被调用,返回的组件都是新创建的
 */
@Configuration(proxyBeanMethods = true) //告诉 SpringBoot 这是一个配置类
public class MyConfig {
    @Bean //给容器中添加组件。方法名=组件的id,返回类型=组件类型,返回值=组件在容器中的实例
    public Person person01(){
        Person person = new Person("xiaoming",20);
        //user 组件依赖了 Pet 组件
        person.setPet(pet());
        return person;
    }

    @Bean
    public Pet pet(){
        return new Pet("泰迪");
    }
}

检测 @Configuration 的代码

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class,args);

        //2.查看所有容器中的组件
        for (String name:context.getBeanDefinitionNames()){
            System.out.println(name);
        }

        //3.从容器中获取组件
        Pet pet = context.getBean("pet",Pet.class);//方式
        System.out.println("组件: "+ (pet == context.getBean("pet", Pet.class))); //输出 true,验证容器中的组件都是单例的

        //4.配置对象本身也在容器中
        MyConfig myConfig = context.getBean(MyConfig.class);
        //输出: com.example.conf.MyConfig$$EnhancerBySpringCGLIB$$1dc93a37@12477988(当 proxyBeanMethods = true 时,此时 myConfig 是加强的代理对象);
        //      com.example.conf.MyConfig@17d238b1(当 proxyBeanMethods = false 时,此时 myConfig 就是普通对象)
        System.out.println(myConfig);

        //5.调用 myConfig 的方法
        Person person1 = myConfig.person01();
        Person person2 = myConfig.person01();
        //输出:
        //     true  -- 当 proxyBeanMethods = true 时,此时 myConfig 是加强的代理对象,它总会检查这个组件是否在容器中存在); 
        //     false -- 直接调用方法。
        System.out.println((person1==person2));
    }
}
  • 配置类中的组件之间无依赖关系时,使用 Lite 模式(即 proxyBeanMethods = false)加速容器启动过程,减少判断。
  • 配置类之间有依赖关系时,使用 Full 模式(即 proxyBeanMethods = true,默认) 

8.底层注解 - @Import 导入组件

@Import 给容器中自动创建的组件,其默认名称就是全类名,比如

//导入的 DBHelper 在容器中组件的名称为 ch.qos.logback.core.db.DBHelper@759d81f3
@Import({DBHelper.class})

9.底层注解 - @Conditional 条件装配

条件装配:满足 Conditional 指定的条件,则进行组件注入。

@Conditional 可以注解在类上和方法上:注解在方法上 Conditional 只对该方法有效;注解在类上,则 Conditional  对整个类有效

Conditional 有以下子类:

  • @ConditionalOnJava:系统的 Java 版本是否符合要求
  • @ConditionalOnBean:容器中存在指定的 Bean
  • @ConditionalOnMissingBean:容器中不存在指定 Bean;
  • @ConditionalOnExpression:满足 SpEL 表达式指定
  • @ConditionalOnClass:系统中有指定的类
  • @ConditionalOnMissingClass:系统中没有指定的类
  • @ConditionalOnSingleCandidate:容器中只有一个指定的 Bean,或这个 Bean 是首选 Bean
  • @ConditionalOnProperty:系统中指定的属性是否有指定的值
  • @ConditionalOnResource:类路径下是否存在指定资源文件
  • @ConditionalOnWebApplication:当前是 Web 环境
  • @ConditionalOnMissingWebApplication:当前不是 Web 环境
  • @ConditionalOnJndi:JNDI 存在指定项

这里使用 @ConditionalOnBean 举例说明:

@Configuration
public class MyConfig {
    @Bean()
    public Pet pet(){
        return new Pet("泰迪");
    }

    @Bean
    @ConditionalOnBean(name = "pet")
    public Person person01(){
        Person person = new Person("xiaoming",20);
        person.setPet(pet());
        return person;
    }
}

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class,args);

        //2.查看所有容器中的组件
        for (String name:context.getBeanDefinitionNames()){
            System.out.println(name);
        }
        
        //当 pet() 方法有 @Bean 注解时,都输出 true;反之,都输出 false
        System.out.println(context.containsBean("pet"));
        System.out.println(context.containsBean("person01"));
    }
}

10.底层注解 - @ImportResource 导入 Spring 配置文件

比如有些公司使用 bean.xml 文件生成 Bean,为了省事,想继续复用 bean.xml,可以使用 @ImportResource 注解。

bean.xml



    
        
    

    
        
        
    

配置类

@Configuration
@ImportResource("bean.xml")
public class MyConfig {
    @Bean()
    public Pet pet(){
        return new Pet("泰迪");
    }

    @Bean
    @ConditionalOnBean(name = "pet")
    public Person person01(){
        Person person = new Person("xiaoming",20);
        person.setPet(pet());
        return person;
    }
}

启动类:

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class,args);

        //输出:
        //      未使用 @ImportResource("bean.xml") 注解时,输出 false
        //      使用 @ImportResource("bean.xml") 注解时,输出 true
        System.out.println(context.containsBean("haha"));
        System.out.println(context.containsBean("hehe"));
    }
}

11.底层注解 - @ConfigurationProperties 配置绑定

@ConfigurationProperties 主要是为了读取 properties 配置文件中的内容,并将它封装到 JavaBean 中供使用。

假设 application.properties 配置文件中有如下内容

11.1 @Component + @ConfigurationProperties 方式

在 Car 类加上【@ConfigurationProperties】注解使配置生效。同时在 Car 类加上【@Component】注解,使该类称为容器中的组件。

注意:配置文件中去除前缀的 key 与类的属性一致的,才会将 key 的值注入到 该组件上。

@Component //只有在容器中的组件,才会拥有SpringBoot提供的强大功能
@ConfigurationProperties(prefix = "car") //prefix 为配置文件的前缀
public class Car {
    private String brand;
    private int price;

    public Car() {
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public int getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

测试方法:

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class,args);

        Car car = context.getBean(Car.class);
        System.out.println(car);
    }
}

11.2 @EnableConfigurationProperties + @ConfigurationProperties 方式

Car 类中只有【ConfigurationProperties】注解:

@ConfigurationProperties(prefix = "car")
public class Car {
    private String brand;
    private int price;

    public Car() {
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public int getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

在 MyConfig 配置类上 加上【@EnableConfigurationProperties】注解

@Configuration
@EnableConfigurationProperties(Car.class)
public class MyConfig {

}

测试方法

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class,args);

        Car car = context.getBean(Car.class);
        System.out.println(car);
    }
}

你可能感兴趣的:(SpringBoot知识)