Web后端开发-原理篇(1)

hello啊各位,我们前期一直在讲解web后端开发都是面向应用层面的,而我们今天讲解的是Web后端开发的最后一个篇章------springboot原理篇,即springboot的原理。

那我们今天讲解的内容包括三个部分,分别是配置优先级、Bean管理、SpringBoot原理

配置优先级

首先是SpringBoot项目当中属性配置的常见方式以及配置的优先级,也就是如果我们用多种方式配置了同一个属性,那到底哪种方式生效?前面的博客我们已经说明了SpringBoot中支持的三种格式的配置文件:application.properties、application.yml、application.yaml,要想配置一个属性,我们通过这三种文件的任意一种都可以,那如果我在三种配置文件中配置了同一个属性(servlet的端口号),那到底哪个配置文件生效呢?我们直接演示一下

启动完之后,我们发现生效的端口号为8081,即properties文件中配置的,那说明这三个配置文件中优先级最高的是properties,我们将其注释,再次重启服务测试另外两个,现在端口号变为了8082,即优先级properties>yml>yaml

那么虽然springboot支持多种格式配置文件,但是在项目开发中,推荐统一使用一种格式的配置

SpringBoot除了支持配置文件属性配置,还支持java系统属性和命令行参数的方式进行属性配置

  • Java系统属性:-Dserver.port=9000
  • 命令行参数: -- server.port=10010

我们如何配置呢?idea已经为我们贴心的提供了可视化的界面

我们可以在VM options里面添加java系统属性,在Program arguments里面添加命令行参数

我们注释掉前面的三种,再次运行,发现端口号为10010,即命令行参数>Java系统属性

那么如果我们之后将项目上线如何进行java系统属性和命令行参数的添加呢?步骤如下

  • 执行maven打包指令package,将其打包成jar
  • 执行java指令,运行jar包
  • java -Dserver.port=9090 - jar tlias-web-management-0.0.1-SNAPSHOT.jar -- server.port=10010

具体不再演示,以上便是我们所介绍的五种优先级了,那么我们再次全部打开,来比较五种配置的优先级,最后配置优先级结果如下

命令行参数>java系统属性>properties文件>yml文件>yaml文件

Bean管理

接着我们来讲解SpringIOC容器中Bean的管理,我们前面已经讲过如何用spring当中提供的注解component,以及它的三个衍生注解,来声明IOC容器中的bean对象,我们也讲解了如何为应用程序注入依赖的bean对象。那这一小节我们主要来讲解Bean的获取、Bean的作用域、第三方Bean的管理等bean的使用细节。

Bean的获取

首先,我们来讲解一下从IOC容器中获取bean对象,默认情况下,Spring项目启动时,会把bean创建好放在IOC容器中,如果想要主动获取这些bean,可以通过如下方式

  • 根据name获取bean:Object getBean(String name)
  • 根据类型获取bean:<T> T getBean(Class<T> requiredType)
  • 根据name获取bean(带类型转换):<T> T getBean(String name, Class<T> requiredType)

接下来我们进行代码演示

java 复制代码
package com.itheima;

import com.itheima.controller.DeptController;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器对象

    @Test
    public void testGetBean(){
        //根据bean的名称获取
        DeptController bean1 = (DeptController) applicationContext.getBean("deptController"); //Bean名称类名首字母小写
        System.out.println(bean1);
        
        //根据bean的类型获取
        DeptController bean2 = applicationContext.getBean(DeptController.class);
        System.out.println(bean2);

        //根据bean的名称及类型获取
        DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);
        System.out.println(bean3);
    }
}

以上便是bean的三种获取方式了,我们运行后发现,这三个从IOC容器中获取的bean对象,其地址值是一样的,那就说明IOC容器中的bean对象有且只有一个,默认情况下这个bean是单例的,我们如何设置其为非单例的呢?那就涉及到我们的作用域了。

Bean的作用域

因为在spring当中容器当中bean对象默认是单例的,即只有一个实例对象,那我们所声明的bean对象到底是单例还是多例,其实是取决于bean的作用域的。

在spring当中支持五种作用域,但后三种在web环境才生效

以上我们只记住前两种即可,那我们如何配置作用域呢?我们可以通过@Scope注解来进行配置作用域。

第三方Bean

讲解完了bean的获取、bean的作用域,接下来我们再来讲解最后一个方面,第三方bean的配置,我们之前声明的dao、service等都是我们自己定义的,为其添加bean只需加上@component注解或其衍生注解即可。但是,在项目开发中还有一种情况,就是这个类不是我们自己定义的,使我们引入的第三方依赖所提供的。此时我们就要用到@Bean注解

@Bean:如果我们要管理的对象来自于第三方(不是自定义的),是无法用@component及衍生注解声明bean的,就需要用到@Bean注解

接下来我们在启动类进行第三方bean的定义并进行测试

java 复制代码
//声明第三方bean对象
    @Bean //将当前方法的返回值交给IOC容器管理,成为ioc容器bean
    public SAXReader saxReader(){
        return new SAXReader();
    }
java 复制代码
@Test
    public void testThirdBean() throws Exception {
        SAXReader saxReader = new SAXReader();

        Document document  = saxReader.read(this.getClass().getClassLoader().getResource("1.xml"));
        Element rootelement = document.getRootElement();
        String name = rootelement.element("name").getText();
        String age = rootelement.element("age").getText();

        System.out.println(name + ":" + age);
    }

但是在项目中我们要保证启动类的纯粹性,所以我们不建议在启动类中定义第三方bean,我们建议单独定义一个config类,并且通过一个@configuration声明一个配置类,在配置类中对第三方bean进行集中管理

java 复制代码
@Configuration
public class CommonConfig {

    //声明第三方bean
    @Bean //将当前方法的返回值对象交给IOC容器管理,成为IOC容器bean
          //通过@Bean注解的name/value属性指定bean名称,如果未指定,默认是方法名
    public SAXReader reader(DeptService deptService){
        System.out.println(deptService);
        return new SAXReader();
    }
}

注意:

  • 通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名
  • 如果第三方bean需要依赖其他对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配
  • 项目中定义的,使用@component及其衍生注解
  • 项目中引入第三方的,使用@Bean注解

SpringBoot原理

最后我们再来剖析SpringBoot的底层应用原理,基于之前的博客,我们可以发现基于springboot开发是非常高效的。SpringBoot使我们能够更加专注的关注业务功能的开发,而不用过多关注框架本身的配置使用,通过springboot的原理分析,我们可以知道为什么springboot如此高效,也能让我们更加熟练地使用springboot进行开发了。

在剖析springboot之前,我们先来简单回顾一下spring框架,spring是目前世界上最流行的java框架,他可以帮助我们更加容易的构建java项目,其所有的框架都是基于SpringFramework这个基础框架的。而我们使用spring框架进行开发会比较繁琐(依赖、配置),所以才会有了我们的SpringBoot,通过SpringBoot来简化spring的开发。为什么SpringBoot框架会较为简单高效呢?是因为springboot提供了两个非常重要的功能,一个是起步依赖,一个是自动配置。接下来我们会根据这两点对springboot的原理进行解析

起步依赖

如果我们使用原始的spring框架进行web程序开发,那么我们就必须自己去引入其需要的依赖,且必须保证其版本对应,而如果我们使用了springboot,就不需这么繁琐,只需引入一个起步依赖,spring-boot-starter-web,即web开发的起步依赖,其里面集成了所有常见的web开发依赖。他将通过maven的依赖传递传递进来,即a依赖b,b依赖c,这会将所有依赖都引入进来。这就是springboot的起步依赖,其原理就是maven的依赖传递。

自动配置

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。

可能这样描述并不能很清楚的理解,我们现在来看一下,我们随便启动一个服务,查看其bean对象,可以发现里面会有这个项目引入以及未引入的bean对象,这些都是springboot自动加载进来的

自动配置原理

我们解析自动配置的原理就是来分析在springboot当中,我们引入的依赖是如何将依赖jar包所提供的这些bean以及配置类直接加载到项目中的springIOC容器当中的

我们如果想要使用第三方包依赖,首先要将其导入,之后我们可以通过以下方式完成

方案一:@Component组件扫描

但是这种方案较为繁琐,每使用一个第三方依赖就需要进行组件扫描,这样会让性能不高

方案二:@import导入。使用@import导入的类会被Spring加载到IOC容器中导入形式有以下几种:

  • 导入普通类
  • 导入配置类
  • 导入ImportSelector
  • @EnableXxxx注解,封装@Import注解

我们通过这四种方式都可以导入配置操作。接下来我们通过源码追踪可以发现

@SpringBootApplication:该注解标识在SspringBoot工程引导类上,是SpringBoot最最最重要的注解。该注解由三部分组成:

  • @SpringBootConfiguration:该注解与@Confirguration注解作用相同,用来声明当前也是一个配置类
  • @ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包
  • @EnableAutoConfirguration:SpringBoot实现自动化配置的核心注解

@Confitional

作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到SpringIOC容器中

位置:方法、类

@Conditional本身是一个父注解,派生出大量的子注解:

  • @ConditionalOnClass:判断环境中是否有对应字节码文件,只有有才注册bean到IOC容器
  • @ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),只有没有才注册bean到IOC容器
  • @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器
案例(自定义starter)

自定义starter

在实际开发中,经常会定义一下公共组件,提供给各个项目团队使用。而在SpringBoot项目中,一般会将这些公共组件封装为SpringBoot的starter

现在我们来完成一个案例

  • 需求:自定义aliyun-oss-spring-boot-starter,完成阿里云OSS操作工具类AliyunOSSUtils的自动配置
  • 目标:引入起步依赖之后,要想使用阿里云OSS,注入AliyunOSSUtils直接使用即可

步骤:

  • 创建aliyun-oss-spring-boot-starter模块
  • 创建aliyun-oss-spring-boot-autoconfigure模块,在starter中引入该模块
  • 在aliyun-oss-spring-boot-autoconfigure模块中的定义自动配置功能,并定义自动配置文件META-INF/spring.xxxx.imports

接下来我们就参照该步骤完成starter的开发

创建完模块把这两个文件留下即可

最后这个案例作者没有跟下来......

并且对于自动配置这点我并没有太听明白,所以只能尽力去写,是在抱歉

以上便是这篇博客的全部内容了,最后还是建议大家去看一下黑马的视频多多理解原理篇,本篇博客如有不正确的,还希望大家多多指正

相关推荐
青山撞入怀11143 小时前
sql题目练习-子查询
java·数据库·sql
番茄Salad4 小时前
Spring Boot项目中Maven引入依赖常见报错问题解决
spring boot·后端·maven
程序员小凯4 小时前
Spring MVC 分布式事务与数据一致性教程
分布式·spring·mvc
Jabes.yang4 小时前
Java求职面试: 互联网医疗场景中的缓存技术与监控运维应用
java·redis·spring security·grafana·prometheus·oauth2·互联网医疗
摇滚侠4 小时前
Spring Boot 3零基础教程,yml配置文件,笔记13
spring boot·redis·笔记
初级炼丹师(爱说实话版)4 小时前
内存泄漏与内存溢出
java
CryptoRzz5 小时前
越南k线历史数据、IPO新股股票数据接口文档
java·数据库·后端·python·区块链
!if5 小时前
springboot mybatisplus 配置SQL日志,但是没有日志输出
spring boot·sql·mybatis
学Java的bb5 小时前
MybatisPlus
java·开发语言·数据库
讓丄帝愛伱5 小时前
Mybatis Log Free插件使用
java·开发语言·mybatis