SpringBoot配置原理

SpringBoot主要的中心思想是

  • 约定大于配置

所以,一般来说在能默认满足的情况下是不进行额外的改变或者配置的

这样可以尽量做到开箱即用!也可以根据自己需要修改相应的部分配置

==而SpringBoot的核心也就是自动装配配置,其仿造了 Java SPI (服务提供发现机制)的一种类加载机制==

  • 可以用来拓展框架和替换组件
  • 常见的框架例子有
    • JDBC
    • SLF4J

Starter(启动器) 分析

在 SpringBoot 中需要导入相应的包都需要写一个相对应的 Starter

而 Starter 中一般不进行代码的编写,只做其他依赖的管理和集中

  • 这样的好处是
    • 一键式导入:导入相应的启动器(starter)后,会将该starter需要的包一并导入
    • 可读性强:代码的编写是在本身原本的框架或者依赖中
    • 符合SpringBoot的思想:可以再自定义一个框架的 autoconfiguration ,这样也可以进行默认的配置做到开箱即用

示例:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot</artifactId>
    <version>2.2.0</version>
  </parent>
    
  <!--  starter本身只做依赖集中管理,不编写任何代码  -->
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <name>mybatis-spring-boot-starter</name>
  <properties>
    <module.name>org.mybatis.spring.boot.starter</module.name>
  </properties>
    
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
      
    <!--  编写的专用配置模块   -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-autoconfigure</artifactId>
    </dependency>
      
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
    </dependency>
  </dependencies>
</project>

image

自定义 Starter

对以上 启动器 进行刨析了解后 ,如果想要自定义一个能够符合SpringBoot的框架,需要以下 三个模块

  • spring-boot-hello:基础业务功能模块
  • spring-boot-starter-hello:启动器
  • spring-boot-autoconfigurer-hello:自动配置依赖

spring-boot-hello

首先创建一个基础的业务功能,实现框架基本实现代码。以下示例将用个简单代码进行演示

package com.test;

public class HelloWorldService {
    public void test(){
        System.out.println("Hello World!");
    }
}

项目结构:

image

spring-boot-autoconfigurer-hello (关键)

然后创建一个自动配置和配置获取的项目

  • autoconfigurer 项目需要导入以下依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>cn.mianju</groupId>
        <artifactId>spring-boot-hello</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

因为会使用到SpringBoot的注解标注 所以需要SpringBoot的依赖。

接着创建一个自动配置类:

@Configuration(proxyBeanMethods = false) //声明该类为配置类
@ConditionalOnWebApplication //当运行在web应用时,该配置类才会生效
@EnableConfigurationProperties(HelloWorldProperties.class) //开启对HelloWorldProperties的配置
public class HelloWorldAutoConfiguration {

    Logger logger = Logger.getLogger(this.getClass().getName());

    @Autowired
    HelloWorldProperties properties; //注入HelloWorldProperties

    @Bean 
  	@ConditionalOnMissingBean // 当没有这个bean时,才会创建该bean 类似自动配置的bean 
    						  // 如果需要满足自己的需要可自行创建同名Bean进行替换
    public HelloWorldService helloWorldService(){
        logger.info("自定义starter项目已启动!");
        logger.info("读取到自定义配置:"+properties.getValue());
        return new HelloWorldService();
    }
}

根据上面的HelloWorldProperties.class 所以还需要创建一个配置文件的 属性类

@ConfigurationProperties("hello.world") // 声明该类为属性类
public class HelloWorldProperties {

    private String value; // 只有一个value属性

    public void setValue(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

最后在resources 文件夹下 创建以下文件

  • ==因为约定大于配置,所以这个文件和路径是不能有变动的==
  • 该文件表示要加载的自动配置类的位置
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

文件内容也就是自动配置类的 全类名

com.test.autoconfigure.HelloWorldAutoConfiguration

项目结构:

image

spring-boot-starter-hello

关于启动器就简单了,因为启动器没有代码,它存在的目的就是将 自动配置类框架业务代码 的依赖进行一个统一整理

然后maven导入starter后就会自动将他所需要的依赖导入,所以只需要导入启动器就可以简单的导入所有的东西

<dependencies>
    <dependency>
        <groupId>cn.mianju</groupId>
        <artifactId>spring-boot-autoconfigure-hello</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>cn.mianju</groupId>
        <artifactId>spring-boot-hello</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

所以只需要保留一个 pom.xml 文件就可以了

项目结构:

image

总结

其实SpringBoot的自动装配核心就在于

  • spring-boot-autoconfigurer-xxx
    • 自动配置类
    • 配置属性类
    • resources中的配置类声明文件

因为springboot源码中有这么一段:

public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
        Assert.notNull(annotation, "'annotation' must not be null");
        ClassLoader classLoaderToUse = decideClassloader(classLoader);
  			//这里直接获取 META-INF/spring/注解类名.imports 中的所有内容
        String location = String.format("META-INF/spring/%s.imports", annotation.getName());
        ...
}

它会获取符合该文件名下的所有配置类和类中的bean并且对应的自动进行配置

所以他能根据你提供的文件去找到你的配置类与属性类

  • spring.factories 是用于对添加包以外的类至spring容器的成为bean
  • META-INF/spring/注解类名.imports 是自动导入并加载配置类的地方

但是其实org.springframework.boot.autoconfigure.AutoConfiguration.imports文件功能和Sping.factories的**==作用是一样==**的

这个用法是SpringBoot 2.7以后出现的,目的也是为引入外部的包

把外部bean纳入到Spring容器,实现外部组件与Spring的集成,主要的区别在于引入的方式有些不同,spring.factories这种方式是在resources下创建/META-INF/spring.factories配置文件,内部是key-value的形式

这种则是创建/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

内部是具体的要导入到Spring环境的中的配置类。

==两种方式有一些区别,以前是应该是用第一种来实现,不过都是用来实现自动装配的。==

文章作者: 面具
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 MianJu —— 这只是一个 Title 而已~
java springboot 面试 springboot java
喜欢就支持一下吧