美文网首页微服务
自定义SpringBoot的starter

自定义SpringBoot的starter

作者: 小丸子的呆地 | 来源:发表于2021-07-10 06:03 被阅读0次

starter是SpringBoot提供的便捷的自动装配组件,通过引入starter包,可以规避以前那种自己添加一大堆依赖,还需要自己注册Bean的方式。可以说是太方便了。

SpringBoot定义了很多常用的starter方便我们应用,官方定义的一般以spring-boot-starter-xxx格式命名,也有一些第三方软件自己定义的starter,这种一般以xxx-spring-boot-starter格式命名。

今天我们自己手撕一个starter。

starter一般分为两部分,一个starter包,一个autoconfiguration包。
starter包一般不包含任何代码,只负责引入一些依赖,比如autoconfiguration的依赖。
autoconfiguration负责定义配置类,自动装载,核心业务Bean。
也有人将所有内容豆丁一到starter包中。

autoconfiguration

首先我们创建一个项目demo-spring-boot-autoconfiguration
pom文件引入:

<?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.5.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.qiejk</groupId>
    <artifactId>demo-spring-boot-autoconfiguration</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

创建一个配置文件类DemoProperties.java

// 这是一个配置文件类
@ConfigurationProperties(prefix = "demo")
public class DemoProperties {
    private String name;
    private String value;

    public String getName() {
        return name;
    }
    public DemoProperties setName(String name) {
        this.name = name;
        return this;
    }
    public String getValue() {
        return value;
    }
    public DemoProperties setValue(String value) {
        this.value = value;
        return this;
    }
}

创建一个核心业务类DemoService.java

// 这是一个工具类
public class DemoService {

    private String name;
    private String value;

    public DemoService(String name, String value) {
        this.name = name;
        this.value = value;
        System.out.println("DemoService init success!");
    }

    public String getName() {
        return name;
    }

    public DemoService setName(String name) {
        this.name = name;
        return this;
    }

    public String getValue() {
        return value;
    }

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

    public void say() {
        System.out.println(name + " say: " + value);
    }
}

创建一个配置类DemoAutoConfiguration.java

@Configuration
// 引入配置文件类
@EnableConfigurationProperties(DemoProperties.class)
// 只有在配置了demo的配置信息时,才进行加载
@ConditionalOnProperty(prefix = "demo", value = "name")
public class DemoAutoConfiguration {

    @Autowired
    private DemoProperties properties;

    @Bean
    public DemoService demoService() {
        return new DemoService(properties.getName(), properties.getValue());
    }
}

在/resources/META-INF/目录下添加spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.qiejk.demo.springboot.autoconfiguration.DemoAutoConfiguration

整体项目结构为:


image.png

执行 mvn clean install -Dskiptests 打包命令。

starter

首先我们创建一个项目demo-spring-boot-starter
pom文件引入:

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

    <dependencies>
        <dependency>
            <groupId>com.qiejk</groupId>
            <artifactId>demo-spring-boot-autoconfiguration</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

执行 mvn clean install -Dskiptests 打包命令。

验证starter

我们随便创建一个SpringBoot项目,引入我们定义的starter

        <dependency>
            <groupId>com.qiejk</groupId>
            <artifactId>demo-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
@SpringBootApplication
public class SpringbootDemoApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootDemoApplication.class, args);
        DemoService demoService = (DemoService)run.getBean("demoService");
        demoService.say();
    }

先不配置参数,直接启动,这里会抛出异常,没有找到demoService对象。
这里是因为我们上面的配置类中,配置了@ConditionalOnProperty(prefix = "demo", value = "name"),这行代码的意思是,只有在配置了demo.name的参数之后,才进行配置类的加载。

在配置文件application.properties中添加配置

demo.name=jack
demo.value=hello

再次启动

/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=64253:/Applications/IntelliJ IDEA.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/tools.jar:/Users/qiejinkai/Work/Liepin/ideaspace/springboot-demo/target/classes:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/boot/spring-boot-starter/2.5.1/spring-boot-starter-2.5.1.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/boot/spring-boot/2.5.1/spring-boot-2.5.1.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/spring-context/5.3.8/spring-context-5.3.8.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/spring-aop/5.3.8/spring-aop-5.3.8.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/spring-beans/5.3.8/spring-beans-5.3.8.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/spring-expression/5.3.8/spring-expression-5.3.8.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/boot/spring-boot-autoconfigure/2.5.1/spring-boot-autoconfigure-2.5.1.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/boot/spring-boot-starter-logging/2.5.1/spring-boot-starter-logging-2.5.1.jar:/Users/qiejinkai/Work/Liepin/mvn/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/qiejinkai/Work/Liepin/mvn/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/qiejinkai/Work/Liepin/mvn/org/apache/logging/log4j/log4j-to-slf4j/2.14.1/log4j-to-slf4j-2.14.1.jar:/Users/qiejinkai/Work/Liepin/mvn/org/apache/logging/log4j/log4j-api/2.14.1/log4j-api-2.14.1.jar:/Users/qiejinkai/Work/Liepin/mvn/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/Users/qiejinkai/Work/Liepin/mvn/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/spring-core/5.3.8/spring-core-5.3.8.jar:/Users/qiejinkai/Work/Liepin/mvn/org/springframework/spring-jcl/5.3.8/spring-jcl-5.3.8.jar:/Users/qiejinkai/Work/Liepin/mvn/org/yaml/snakeyaml/1.28/snakeyaml-1.28.jar:/Users/qiejinkai/Work/Liepin/ideaspace/demo-spring-boot-starter/target/classes:/Users/qiejinkai/Work/Liepin/ideaspace/demo-spring-boot-autoconfiguration/target/classes:/Users/qiejinkai/Work/Liepin/mvn/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar com.qiejk.springbootdemo.SpringbootDemoApplication

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.1)

2021-07-09 09:20:39.020  INFO 23563 --- [           main] c.q.s.SpringbootDemoApplication          : Starting SpringbootDemoApplication using Java 1.8.0_181 on bogon with PID 23563 (/Users/qiejinkai/Work/Liepin/ideaspace/springboot-demo/target/classes started by qiejinkai in /Users/qiejinkai/Work/Liepin/ideaspace/springboot-demo)
2021-07-09 09:20:39.030  INFO 23563 --- [           main] c.q.s.SpringbootDemoApplication          : No active profile set, falling back to default profiles: default

DemoService init success!
2021-07-09 09:20:41.873  INFO 23563 --- [           main] c.q.s.SpringbootDemoApplication          : Started SpringbootDemoApplication in 5.221 seconds (JVM running for 9.744)
jack say: hello

Process finished with exit code 0

OK! 搞定。

总结

  1. 自定义starter命名规范:xxx-spring-boot-starter
  2. starter组成为 一个starter包(负责引入依赖),一个autoconfiguration包(负责实现装配)
  3. autoconfiguration包定义对应的properties类,configuration类,核心业务类。
  4. autoconfiguration包的/resources/META-INF/目录下添加spring.factories文件,并配置org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.qiejk.demo.springboot.autoconfiguration.DemoAutoConfiguration,这步是SpringBoot装配的核心,只有添加了这个内容,SpringBoot才会进行自动装配。

相关文章

网友评论

    本文标题:自定义SpringBoot的starter

    本文链接:https://www.haomeiwen.com/subject/dejtpltx.html