SpringBoot自定义starter操作

自定义Starter

1.Starter介绍    

Starter场景启动器是Spring Boot中一种非常重要的机制,它将繁琐的配置统一集成到stater中,我们只需要通过在Maven将starter的依赖导入项目,SpringBoot 就能自动扫描并加载相应的默认配置。starter的出现简化了开发人员的工作量,从繁琐的框架配置中解救出来,让更多的时间专注在业务逻辑的开发,提高了开发效率。

2.命名规范    

SpringBoot 提供的 starter 以 spring-boot-starter-xxx 的形式命名。为了与 SpringBoot 生态提供的 starter 进行区分,官方建议第三方开发者或技术(例如 Druid、Mybatis 等等)厂商自定义的 starter 使用 xxx-spring-boot-starter 的形式命名,例如 mybatis-spring-boot-starter、druid-spring-boot-starter 等等。

3.模块规范    

Spring Boot 官方建议我们在自定义 starter 时,创建两个 Module :autoConfigure Module(SpringBoot模块) 和 starter Module(Maven 模块),其中 starter Module 依赖于 autoConfigure Module。当然,这只是 Spring Boot 官方的建议,并不是硬性规定,若不需要自动配置代码和依赖项目分离,我们也可以将它们组合到同一个 Module 里。

4.自定义Starter

1)starter启动原理

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

 

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

    • @ConditionalOnMissingBean   //条件装配

    • @EnableConfigurationProperties(xxxProperties.class)  //开启属性绑定功能(在配置文件中修改值)+将绑定类xxxProperties加入容器

    • @Bean //生成组件

    • ......             

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

5.自定义starter具体实操

(1)创建一个名为 spring-boot-customer-starter  空工程,工程下面新建两个模块

 

 

 

 

 

 

 

1)hello-spring-boot-starter(场景启动器,普通Maven工程);

 

 

 

2)hello-spring-boot-starter-autoconfigure(自动配置包,需用用到Spring Initializr创建的Maven工程);

 

 

 

 

 

 

 

 

 

 

 3)hello-spring-boot-starter无需编写什么代码,只需让该工程引入hello-spring-boot-starter-autoconfigure依赖

 hello-spring-boot-starter 的 pom.xml 如下:

<?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.liang</groupId>
    <artifactId>hello-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>

<!--引入 hello-spring-boot-starter-autoconfigure 依赖 --> <dependencies> <dependency> <groupId>com.liang</groupId> <artifactId>hello-spring-boot-starter-autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>

 

hello-spring-boot-starter-autoconfigure的 pom.xml 如下:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.liang</groupId>
    <artifactId>hello-spring-boot-starter-autoconfigure</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello-spring-boot-starter-autoconfigure</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
</project>

 

(2)创建hello-spring-boot-starter-autoconfigure中的整个目录

 

 (3)定义Properties类

在com.liang.hello.bean包下创建一个实体类:HelloProperties,通过它来映射配置信息。

package com.liang.hello.bean;

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

/**
 * @ConfigurationProperties("hello")是springboot提供读取配置文件的一个注解
 *  1)让当前类的属性和配置文件中以 hello开头的配置进行绑定
 *  2)以 hello为前缀在配置文件中读取/修改当前类中的属性值
 */
@ConfigurationProperties("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;
    }
}

 

(4)定义Service类

在com.liang.hello.service包下创建一个HelloService类:实现具体业务功能。

package com.liang.hello.service;

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

/**
 * 默认不要放在容器中
 */
public class HelloService {

    /**
     * @Autowired:自动注入属性
     * 在bean中的属性上通过@Autowired实现自定义bean类型的属性注入
     * 使用是对应的bean必须被spring管理,即手动配置了bean或者在类上添加了@Component注解
     *   DI:就是注入功能,通俗的说就是给IOC创建出来的对象属性赋值
     */
    @Autowired
    private HelloProperties helloProperties;

    //sayHello(String userName)方法
    public String sayHello(String userName)
    {
        return helloProperties.getPrefix()+": "+userName+">> "+helloProperties.getSuffix();
    }
}

 

(5)定义自动配置类

在com.liang.hello.autoConfig包下创建一个HelloAutoConfiguration配置类。

package com.liang.hello.autoConfig;

import com.liang.hello.bean.HelloProperties;
import com.liang.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;

@Configuration //标识配置类
@EnableConfigurationProperties(HelloProperties.class)//开启属性绑定功能+默认将HelloProperties放在容器中
public class HelloAutoConfiguration {

    /**
     * @Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。
     * 产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中;
     *
     * @ConditionalOnMissingBean(HelloService.class)
     * 条件装配:容器中没有HelloService这个类时标注的方法才生效 / 创建一个HelloService类
     */
    @Bean
    @ConditionalOnMissingBean(HelloService.class)
    public HelloService helloService()
    {
        HelloService helloService = new HelloService();
        return helloService;
    }
}

 

(6)创建spring.factories文件

1)Spring Factories机制是Spring Boot中一种服务发现机制,这种机制与Java SPI类似。

2)Spring Boot会自动扫描所有Jat包类路径下META-INF/spring.factories文件,并读取其中的内容,进行实例化。这种机制也是Spring Boot Starter的基础。

3)在helllo-spring-boot-starter-autoconfigure 的类路径下(resources )中创建一个 META-INF 文件夹,并在 META-INF 文件夹中创建一个 spring.factories 文件,并添加如下配置

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.liang.hello.autoConfig.HelloAutoConfiguration

4)注意:在spring.factories中显示指定这些配置类的目录,注意“,”后不要有空格之类的符号,就只写该类的全路径,不然会出现无法找到此bean的错误。

 

(7)构建starter

利用maven插件将两个工程打包到本地仓库中。

1)自定义的本地仓库目录

 

 

 

2)将写好的项目打包到本地仓库中

 

 

  

                                                    最后自定义的starter构建成功!

 

总结使用引入starter --- xxxAutoConfiguration --- 容器中放入组件 ---- 绑定xxxProperties ---- 配置项修改

总结自定义

a.创建一个空工程,在里面创建xxx-spring-boot-starter工程+创建 xxx-spring-boot-starter-autoConfigure工程;

b.在xxx-spring-boot-starter工程中引入xxx-spring-boot-starter-autoConfigure工程的依赖;

c.创建xxxAutoConfiguration,开启自动属性绑定功能(绑定xxxProperties),里面添加需要组件;

d.在 xxx-spring-boot-starter-autoConfigure工程的 resources 包下创建META-INF/spring.factories文件,里面加入自动配置类的类路径;

e.分别对两个工程进行clean+install操作,将自定义的starter编译并打包到本地仓库,注意时刻保持最新状态。


 

补充:maven的install可以将项目本身编译并打包到本地仓库,这样其他项目引用本项目的jar包时不用去私服上下载jar包,直接从本地就可以拿到刚刚编译打包好的项目的jar包,很灵活,避免每次都需要重新往私服发布jar包的痛苦。

 


 

6、创建一个测试项目,引入自定义的starter依赖使用

(1)用Spring Initializr创建名为hello-spring-boot-starter-test工程,引入hello-spring-boot-starter依赖+spring web依赖测试

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

 

(2)创建配置文件application.yaml,修改相应的属性配置项

 

 (3)定义Controller

在com.liang.hello.controller包下创建一个HelloController类:

package com.liang.hello.controller;

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

@RestController //=@Controller+@ResponseBody
public class HelloController {

    @Autowired
    HelloService helloService;

    @GetMapping("/hello") //处理get请求方式的/hello请求路径
    public String sayHello()   //处理方法
    {
        String s = helloService.sayHello("阿娇");
        return s;
    }
}

 

(4)运行

 

 

 运行成功!自定义starter有效。

 

posted @ 2022-04-10 21:15  Lfollow  阅读(301)  评论(0编辑  收藏  举报