SpringBoot原理

发布时间 2023-12-21 16:35:52作者: 奕帆卷卷

配置

  • SpringBoot中支持三种格式的配置文件

.properties

.yml

.yaml

虽然Springboot支持多种文件配置,但是通常在项目开发中,我们一般推荐使用yml文件配置

优先级

在SpringBoot项目中,常见的属性配置有5种,3种配置文件加上两种外部的配置,生效优先级

  • SrpingBoot配置优先级(低 -> 高):

1.application.yaml(忽略)

2.application.yml

3.application.properties

4.java系统属性(-Dxxx=xxx)

5.命令行参数(--xxx=xxx)

Bean管理

获取Bean

默认情况下,Springboot项目在启动的时候会自动创建IOC容器,并在创建好的bean对象存放在IOC容器当中,以供应用程序直接进行依赖注入

我们有三种方式可以从IOC容器中获取Bean

  • 根据name获取bean
  • 根据类型获取bean
  • 根据name获取bean(带类型转换)

我们要先拿到IOC容器对象,才能获取bean对象

我们直接将IOC容器对象注入进来就可以

测试类:

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

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

    //获取bean对象
    @Test
    public void testGetBean(){
        //根据bean的名称获取
        DeptController bean1 = (DeptController) applicationContext.getBean("deptController");
        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对象只有一个

Bean作用域

在IOC容器中,默认bean对象是单例模式,也就是上面案例输出的bean对象地址值相同,即容器中同名称的bean只有一个实例

在Spring中支持五种作用域,后三种在Web环境中才生效

作用域 说明
singleton 容器内同名称的bean只有一个实例(单例)(默认)
prototype 每次使用该bean时会创建新的实例(非单例)
request 每个请求范围内会创建新的实例(web环境中,了解)
session 每个会话范围内会创建新的实例(web环境中,了解)
application 每个应用范围内会创建新的实例(web环境中,了解)

在IOC容器中默认是单例模式,我们可以通过Spring中的@Scope注解来进行配置作用域

@Scope("prototype")

IOC容器中的bean在容器启动时被创建,可以使用@Lazy注解来延迟初始化(延迟到第一次使用时)

第三方Bean

我们在项目中自己定义的类,如果我们要声明这些bean,我们只需要在类上加上@Component以及它的三个衍生注解@Controller,@Service,@Repository.就可以来声明这个bean对象

但是如果在项目开发中,有类不是我们自己编写的,而是我们引入的第三方依赖当中提供的。

当我们需要使用其他类时,我们无法在第三方类上添加@Component注解或衍生注解,那么如何定义第三方的bean呢,我们就需要用到@Bean注解

列如我们要使用SAXReader的方法我们只需要在启动类上添加@Bean标识的方法就可以了

  • 在启动类上添加@Bean标识的方法
@SpringBootApplication
public class SpringbootWebConfig2Application {

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

    //声明第三方bean
    @Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean
    public SAXReader saxReader(){
        return new SAXReader();
    }
}

xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<emp>
    <name>Tom</name>
    <age>18</age>
</emp>

测试类:

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private SAXReader saxReader;

    //第三方bean的管理
    @Test
    public void testThirdBean() throws Exception {
        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);
    }

    //省略其他代码...
}

重启SpringBoot服务,执行测试方法后,控制台输出日志:

Tom : 18

注意:在项目中我们自己定义的类,我们想要把这些类交给IOC容器管理,我们可以直接使用@Component或者衍生注解来声明就可以,

如果这个类不是我们自己定义的,而是引入的第三方依赖当中提供的类,我们想把这个类交给IOC容器管理,此时我们就需要在配置类中定义一个方法,在方法上加上一个@Bean注解

SpringBoot原理

前言

我们接下来来刨析一下SpringBoot的底层原理,因为SpringBoot能够是我们更加简单的进行业务能力的开发,不必过多的关注框架本身的配置使用。

Spring是世界上最流行Java框架,他可以帮助我们更加快速的,更加容易的构建Java项目。在Spring家族中有很多的优秀的框架,而所有的框架都是基于一个基础框架的SpringFramework。

由于Spring框架直接进行项目开发,会比较繁琐

  • 在pom.xml中依赖配置比较繁琐,在项目开发时,需要自己去找到对应的依赖,还需要找到依赖它所配套的依赖以及对应版本,否则就会出现版本冲突问题。
  • 在使用Spring框架进行项目开发时,需要在Spring的配置文件中做大量的配置,这就造成Spring框架入门难度较大,学习成本较高。

所以我们在Spring框架4.0版本之后,又推出了一个全新的框架SpringBoot,我们可以通过SpringBoot来简化Spring框架的开发,直接基于SpringBoot来构建Java项目

为什么要使用SpringBoot来构建开发呢?

主要有两个特别重要的功能

  1. 起步依赖
  2. 自动配置

起步依赖

我们没有使用SpringBoot,用的是Spring框架进行web程序的开发,此时我们就需要引入web程序开发所需要的一些依赖。

spring-webmvc依赖:这是Spring框架进行web程序开发所需要的依赖

servlet-api依赖:Servlet基础依赖

jackson-databind依赖:JSON处理工具包

如果要使用AOP,还需要引入aop依赖、aspect依赖

项目中所引入的这些依赖,还需要保证版本匹配,否则就可能会出现版本冲突问题。

如果我们使用SpringBoot,就只需要引入一个依赖就可以了,这就是Web开发的起步依赖:springboot-starter-web

原理是 Maven的依赖传递

在起步依赖中以提供了当前程序开发所需要的所有常见依赖,只需要引入这一个依赖,其他依赖就会自动的通过Maven的依赖传递进来

自动配置

自动配置就是当Spring容器启动后,一些配置类,bean对象就自动存入IOC容器中。不需要手动声明,简化操作。

SpringBoot项目在启动时通过自动配置完成了bean对象的创建。

在启动类中,有一个注解@SpringBootApplication,点进注解,有三个注解是比较重要的。

  • @SpringBootConfiguration:进去这个注解我们可以发现底层是Configuaration注解,也就是支持JavaConfig的方式来进行配置(使用Configuration配置类等同于XML文件)

  • @EnableAutoConfiguration:开启自动配置功能

  • @ComponentScan:扫描注解,默认是扫描当前类下的package。将

    `@Controller/@Service/@Component/@Reposito

    ry`等注解加载到IOC容器中

“约定大于配置”,在SpringBoot中是怎么做的呢,其实靠的就是@EnableAutoConfiguration,简单来说,这个注解可以帮助我们自动载入应用程序所需要的所有默认配置,点进去我们会发现

  • @AutoConfigurationPackage:自动配置包
  • @Import:给IOC容器导入组件

我们再进入@AutoConfigurationPackage

可以发现,依靠的还是@Import注解,再点进去查看,我们发现重要的就是以下的代码:

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
        BeanDefinitionRegistry registry) {
    register(registry, new PackageImport(metadata).getPackageName());
}

默认的情况下就是将:主配置类(@SpringBootApplication)的所在包及其子包里边的组件扫描到Spring容器中。

我们回到@Import(AutoConfigurationImportSelector.class)这句代码上,再点进去AutoConfigurationImportSelector.class

  • FACTORIES_RESOURCE_LOCATION的值是META-INF/spring.factories

  • Spring启动的时候会扫描所有jar路径下的META-INF/spring.factories,将其文件包装成Properties对象

  • 从Properties对象获取到key值为EnableAutoConfiguration的数据,然后添加到容器里边。

    其中@EnableAutoConfiguration是关键(启用自动配置),内部实际上就去加载META-INF/spring.factories文件的信息,然后筛选出以EnableAutoConfiguration为key的数据,加载到IOC容器中,实现自动配置功能!