springboot自定义stater最详细原理分析与案例实现

1、starter启动原理

  • starter-pom引入 autoconfigurer 包

  • autoconfigure包中配置使用 META-INF/spring.factoriesEnableAutoConfiguration 的值,使得项目启动加载指定的自动配置类

    这里的autoconfigure指的是下面这个我们通过xxx-spring-boot-starter依赖的xxx-spring-boot-starter-autoconfigure
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y3f4Sw1F-1630597622829)(SpringBoot.assets/image-20210902224209928.png)]

  • 编写自动配置类 xxxAutoConfiguration -> xxxxProperties

  • @Configuration
    @Conditional
    @EnableConfigurationProperties
    @Bean

引入starter — xxxAutoConfiguration — 容器中放入组件 ---- 绑定xxxProperties ---- 配置项

2、自定义starter

1、创建xxx-spring-boot-starter类

我们通过分析源码可以得知,springboot提供的starter,其实并没有定义什么内容,只是依赖了对应的starter的autoconfigure,通过导入starter去开启导入对应的组件

这里我们创建一个starter类:xiaoshuang-hello-spring-boot-starter

在pom.xml文件中去引入对应的xiaoshuang-hello-spring-boot-starter-autoconfigure

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <groupId>com.shuang</groupId>
    <artifactId>xiaoshuang-hello-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>
        <dependency>
            <groupId>com.shuang</groupId>
            <artifactId>xiaoshuang-hello-spring-boot-starter-autoconfigure</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

2、创建xxx-spring-boot-starter-autoconfigure

创建starter对应的autoconfigure,其中包含了我们定义的业务类,而业务类会使用**@Autowired**去导入xxxProperties,而对应的xxxProperties会使用@ConfigurationProperties去获取properties的值;

之后我们需要去创建对应的xxxAutoConfiguration,并使用@Configuration,@Conditionalxxx进行条件过滤,已确定是否开启该自动配置;使用@EnableAutoConfiguration将xxxProperties添加到IOC容器中,并开启指定类与properties文件对应前缀的绑定;在xxxAutoConfiguration中需要去定义返回值为要导入容器的组件,并使用@Bean添加到IOC容器

这里创建对应xiaoshuang-hello-spring-boot-starter的autoConfigure类:

xiaoshuang-hello-spring-boot-starter-autoconfigure

1、创建HelloProperties
package com.shuang.hello.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @Author: 小爽帅到拖网速
 */
@ConfigurationProperties("xiaoshuang.hello")
public class HelloProperties {
    
    
  private String prefix;
  private String suffix;

  public String getPrefix() {
    
    
    return prefix;
  }

  public void setPrefix(String prefix) {
    
    
    this.prefix = prefix;
  }

  public String getSuffix() {
    
    
    return suffix;
  }

  public void setSuffix(String suffix) {
    
    
    this.suffix = suffix;
  }
}

2、创建依赖HelloProperties的业务类
package com.shuang.hello.service;

import com.shuang.hello.bean.HelloProperties;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @Author: 小爽帅到拖网速
 */
public class HelloService {
    
    

  @Autowired
  private HelloProperties helloProperties;

  public String sayHello(String name) {
    
    
    return helloProperties.getPrefix() + ": "+name +"---->"+helloProperties.getSuffix();
  }
}

3、创建自动配置类并添加到IOC中
package com.shuang.hello.auto;

import com.shuang.hello.bean.HelloProperties;
import com.shuang.hello.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: 小爽帅到拖网速
 */
@Configuration   // 添加到IOC容器
/**
 * @EnableConfigurationProperties(HelloProperties.class)
 * 1、开启HelloProperties与对应的properties文件对应的前缀绑定
 * 2、将HelloProperties加入到容器中
 */
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
    
    

  // 如果当前容器没有HelloService,就将执行以下方法将HelloService加入到容器中
  // 如果当前容器有HelloService,就不会执行以下方法
  @ConditionalOnMissingBean(HelloService.class)
  @Bean
  public HelloService helloService(){
    
    
    return new HelloService();
  }
}

4、resources下创建META-INF/spring-factories

我们在分析xxxAutoConfiguration是最终都会走到xxx组件对应的META-INF/spring-factories文件下

经过分析后我们可以知道,springboot的自动配置原理,最终通过META-INF/spring-factories,查找到对应的xxx.xxx.xxxAutoConfiguration(全类限定名),并运行这个类

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.shuang.hello.auto.HelloServiceAutoConfiguration

3、添加到maven仓库

1、先将xxx-spring-boot-starter-autoconfigure添加到maven中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u98LNNZp-1630597622834)(SpringBoot.assets/image-20210902232508358.png)]

2、再将xxx-spring-boot-starter添加到maven中,跟上面的是一样的操作

4、测试自定义starter

1、创建测试项目,并导入xxx-spring-boot-starter依赖

<dependency>
    <groupId>com.shuang</groupId>
    <artifactId>xiaoshuang-hello-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

2、创建测试Controller

package com.shuang.hello.controller;

import com.shuang.hello.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: 小爽帅到拖网速
 */
@RestController
public class HelloController {
    
    

  @Autowired
  HelloService helloService;

  @GetMapping("/hello")
  public String sayHello(){
    
    
    String hello = helloService.sayHello("郑爽");
    return hello;
  }
}

注意:如果遇到@Autowired失败,可以参考以下这篇文章
https://blog.csdn.net/weixin_46195957/article/details/120068904

5、原理总结

我们在测试Controller中使用了@Autowired去自动导入了我们在hello-spring-boot-starter-autoconfigure定义的业务类,在自动导入之前,springboot就已经扫描完所有导入starter的类,最终会扫描到每个starter类依赖的xxxAutoConfigure下的META-INF/spring.factories,通过该文件获取到xxxAutoConfiguration的全类限定名,就会去加载我们写在xxx-spring-boot-xxxAutoConfigure项目下的xxxAutoConfiguration类,也就是我们前面定义的HelloServiceAutoConfiguration,通过判断是否执行创建HelloService,从而决定是否对HelloProperties.class进行下一步操作(开启与对应properties的前缀进行绑定以及添加到IOC容器)

HelloServiceAutoConfiguration中使用**@ConditionalOnMissingBean(HelloService.class),如果我们在当前容器中也就是测试项目容器有HelloService.class的存在,也就不会去执行HelloServiceAutoConfiguration**下的某个对应方法

这里我们可以做个测试(当前容器以及存在HelloService.class

package com.shuang.hello.config;

import com.shuang.hello.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: 小爽帅到拖网速
 */
@Configuration
public class MyConfig {
    
    

  @Bean
  public HelloService helloService(){
    
    
    return new HelloService();
  }
}

可以看到当我们添加创建了HelloService并添加到IOC容器中,就不会去执行HelloServiceAutoConfiguration下对应的helloService()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ulueYR7-1630597622837)(SpringBoot.assets/image-20210902234340615.png)]

猜你喜欢

转载自blog.csdn.net/weixin_46195957/article/details/120072225
今日推荐