笔记

万物寻其根,通其堵,便能解其困。
  博客园  :: 新随笔  :: 管理

关于Spring Boot启动器的自定义处理笔记

Posted on 2024-05-16 11:01  草妖  阅读(6)  评论(0)    收藏  举报

笔记参照地址,如有学习,请跳转查看更加详细描述:华为二面:SpringBoot如何自定义Starter? - 码农Academy - 博客园 (cnblogs.com)

一、创建启动器

1.定义一个启动器项目WebStarterDemo,具体结构如下:

2.pom.xml所需依赖

<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>com.lancoo</groupId>
        <artifactId>WebTool</artifactId>
        <version>1.0.0</version>
    </parent>

    <groupId>com.sbproject</groupId>
    <artifactId>WebStarterDemo</artifactId>
    <packaging>jar</packaging>

    <name>WebStarterDemo</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
      <!-- 自动化配置 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency>
      <!-- 其中spring-boot-configuration-processor这个依赖主要用于IDEA支持和编译时生成元数据。 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> </project>

这里有一个需要注意的地方:如果不存在父项目,那么必定需要在该项目指定指定打包,打包脚本如下(父级的pom.xml):

<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>
    <modules>
        <module>LogPlugIn</module>
        <module>WebStarterDemo</module>
        <module>WebStarterDemo</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.lancoo</groupId>
    <artifactId>WebTool</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <name>WebTool</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>2.7.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>2.7.2</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.7.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-autoconfigure</artifactId>
                <version>2.7.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <version>2.7.2</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>2.0.11</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.24</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>

            <dependency>
                <groupId>joda-time</groupId>
                <artifactId>joda-time</artifactId>
                <version>2.10.14</version>
            </dependency>
            <!-- 上传obs引入 -->
            <dependency>
                <groupId>com.huaweicloud</groupId>
                <artifactId>esdk-obs-java</artifactId>
                <version>[3.21.11,)</version>
            </dependency>
            <!-- 上传obs需要将String转换为inputStream流上传 -->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.11.0</version>
            </dependency>

        </dependencies>
    </dependencyManagement>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
            <!-- 通过查看spring boot源码可以知道,在加载上下文配置、监听器的过程中,自动配置回去加载.factories配置的全限定引用符号进而加载相关的bean -->
            <!-- 所以,这里一定要指定资源文件,不然打包的时候,无法将自动配置的内容打包,出现的问题是:当您在新的项目进行@Autowired自动装配时,将会报错 -->
<include>**/*.factories</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                    <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.编写启动器相关功能类WebStarter.java 

package com.sbproject;

/**
 * Starter启动器功能
 * */
public class WebStarter
{
    public String WebStarterEntrance(){
        return "这是Starter启动器入口....";
    }
}

 4.配置bean(WebStarterBean.java 

package com.sbproject;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebStarterBean {
    @Bean
    public WebStarter getWebStarter(){
        return new WebStarter();
    }
}

注:这里需要注意使用@Configuration和@AutoConfiguration的区别,笔记末尾有提到。

5.配置自动配置的.factories(src\main\resources\META-INF\spring.factories)

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sbproject.WebStarterBean

 

二、在项目中引用启动器

1.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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <groupId>com.namejr</groupId>
    <artifactId>FirstSBDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.14</version>
        </dependency>
        <!-- 添加本地启动器jar包的依赖 -->
        <dependency>
            <groupId>com.sbproject</groupId>
            <artifactId>WebStarterDemo</artifactId>
            <version>1.0.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/WebStarterDemo.jar</systemPath>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.json</include>
                    <include>**/*.txt</include>
                    <include>**/*.mp3</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <!-- 注册webapp目录为资源目录 -->
                <directory>src/main/webapp</directory>
                <targetPath>META-INF/resources</targetPath>
                <includes>
                    <include>**/**</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                    <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
                </configuration>
            </plugin>
            <plugin>
                <!-- 配置jar包打包工具 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <webResources>
                        <resource>
                            <directory>${project.basedir}/libs</directory>
                            <targetPath>WEB-INF/lib</targetPath>
                            <includes>
                                <include>**/*.jar</include>
                            </includes>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.直接引入启动器使用(PublicController.java

package com.namejr.controller;

import com.namejr.serviceImpl.PublicServiceImpl;
import com.sbproject.WebStarter;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/api/public")
public class PublicController {
    @Autowired
    private PublicServiceImpl pServiceImpl;

    @Autowired
    private WebStarter getWebStarter;

    @RequestMapping(value = "/getServerTime", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    public String getServerTime() {
        return DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
    }

    @RequestMapping(value = "/runStarter", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    public String runStarter() {
        return getWebStarter.WebStarterEntrance();
    }
}

调用输出:

 

 三、获取配置信息

启动器内部配置:
1.WebStarterProperties.java 
package com.sbproject;

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

/**
 * 获取配置中心信息
 * */
@Configuration
@ConfigurationProperties(prefix = "web-starter")
public class WebStarterProperties {
    // 字段
    private String wsname;

    public String getWsname() {
        return wsname;
    }

    public void setWsname(String wsname) {
        this.wsname = wsname;
    }
}

2.注册bean

package com.sbproject;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebStarterBean {
    @Bean
    public WebStarter getWebStarter(){
        return new WebStarter();
    }
    @Bean
    public WebStarterProperties wsProperties(){
        return new WebStarterProperties();
    }
}

3.配置启动器接口

package com.sbproject;

/**
 * Starter启动器功能
 * */public class WebStarter
{public String webStarterEntrance(){
        return "这是Starter启动器入口....";
    }
}

外部项目引用:

1.application.properties配置需要的配置信息

server.port=8080

logging.config=classpath:logback-spring.xml

web-starter.wsname=namejr

2.直接使用

package com.namejr.controller;

import com.namejr.serviceImpl.PublicServiceImpl;
import com.sbproject.WebStarter;
import com.sbproject.WebStarterProperties;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/api/public")
public class PublicController {
    @Autowired
    private PublicServiceImpl pServiceImpl;
    @Autowired
    private WebStarter getWebStarter;
    @Autowired
    private WebStarterProperties wsProperties;

    @RequestMapping(value = "/getServerTime", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    public String getServerTime() {
        return DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
    }

    @RequestMapping(value = "/runStarter", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    public String runStarter() {
        return getWebStarter.webStarterEntrance()+"<====>"+wsProperties.getWsname();
    }
}

输出:

 

 四、额外补充启动器内部默认配置(也可以在文件中将private String wsname;改为默认值:private String wsname="";

启动器内部配置:

1. WebStarterDemo\src\main\resources\META-INF中添加webstarter-dev.properties配置文件

web-starter.wsname=this is the default configuration file

2.配置bean中的WebStarterBean.java中引入配置文件 

注:@PropertySource要在配置bean中引入。

package com.sbproject;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource(value = "classpath:/META-INF/webstarter-dev.properties")
public class WebStarterBean {
    @Bean
    public WebStarter getWebStarter(){
        return new WebStarter();
    }
    @Bean
    public WebStarterProperties wsProperties(){
        return new WebStarterProperties();
    }
}

 外部项目配置:

1.在项目中不配置(注销)web-starter.wsname,直接输出 

package com.namejr.controller;

import com.namejr.serviceImpl.PublicServiceImpl;
import com.sbproject.WebStarter;
import com.sbproject.WebStarterProperties;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/api/public")
public class PublicController {
    @Autowired
    private PublicServiceImpl pServiceImpl;
    @Autowired
    private WebStarter getWebStarter;
    @Autowired
    private WebStarterProperties wsProperties;

    @RequestMapping(value = "/getServerTime", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    public String getServerTime() {
        return DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
    }

    @RequestMapping(value = "/runStarter", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    public String runStarter() {
        return getWebStarter.webStarterEntrance()+"<====>"+wsProperties.getWsname();
    }
}

 输出内容:

 

 当开放外部项目的application.properties配置文件时,访问输出如下:

外部的application.properties文件:
web-starter.wsname=namejr

 

 

 @Configuration和@AutoConfiguration的区别

详情可以查看Springboot Configuration 和 AutoConfiguraton - 简书 (jianshu.com)

相同点:都能够进行功能的配置(包括实现自动配置)。

不同点

1、加载顺序不同:@Configuration会优先@AutoConfiguration加载,但是@Configuration的加载顺序是不可控的,而@AutoConfiguration可以通过@AutoConfigureAfter、@AutoConfigureBefore和@AutoConfigureOrder来控制类的加载顺序。

2、@Configuration是通过@ComponentScan进行指定扫描的,会先扫描所有被扫描到的配置文件,然后再去加载Bean;@AutoConfiguration是通过自动配置文件(classpath*:META-INF/spring.factories)的配置一个个去扫描并加载Bean。注:如果自动装配类使用@ComponentScan扫描,并且类名在自动配置文件中,那么将会被扫描两次并且@AutoConfigureAfter、@AutoConfigureBefore和@AutoConfigureOrder会失效。

 

、、、