springboot自定义starter

在使用springboot的时候,只需要添加一些starter依赖,就能极大地简化开发操作,那么如何自定义一个starter?

创建简单的 starter 项目

这个项目不需要特别多的依赖,只需一个

1
implementation("org.springframework.boot:spring-boot-autoconfigure")

编写service,这是我们需要自动配置的服务。

1
2
3
4
5
6
7
8
9
10
public interface HelloService {
String sayHello();
}

public class HelloServiceImpl implements HelloService {
@Override
public String sayHello() {
return "hello world";
}
}

编写配置文件

1
2
3
4
5
6
7
8
9
@Configuration
public class AutoConfiguration {

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

接着在resources文件夹下创建META-INF文件夹,在文件夹中创建spring.factories文件,文件内容为:

注意修改自己的包名

1
org.springframework.boot.autoconfigure.EnableAutoConfiguration=net.peihuan.starterdemo.config.AutoConfiguration

代码编写完成了,现在需要发布 jar 包,这里我使用了nexus搭建的私有仓库。

修改build.gradle文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
buildscript {

ext {
springBootVersion = '2.1.8.RELEASE'
}

dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
repositories {
mavenLocal()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
}
}


apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
//apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'


group 'net.peihuan'
version '0.0.5'

sourceCompatibility = 1.8

repositories {
mavenLocal()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
}

dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
}
}

dependencies {
implementation("org.springframework.boot:spring-boot-autoconfigure")
}


task sourcesJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allJava
}

task javadocJar(type: Jar) {
classifier = 'javadoc'
from javadoc.destinationDir
}


publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourcesJar
artifact javadocJar
groupId project.group
artifactId project.name
version project.version
pom {
name = project.name
description = project.description
}
}
}
repositories {
maven {
// 修改仓库地址为你自己的
def releasesRepoUrl = "http://repo.peihuan.net/repository/maven-releases/"
def snapshotsRepoUrl = "http://repo.peihuan.net/repository/maven-snapshots/"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
credentials {
// 修改用户名密码
def nexusUsername = "your-username"
def nexusPassword = "your-password"
username nexusUsername
password nexusPassword
}
}
}
}

如果发布出现一些奇怪的错误,检查下gradle版本,这里给出使用的

1
2
3
4
5
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

你也可以发布到本地maven仓库,这样更简单。

创建测试项目引入starter

只需要在build.gradle文件中添加自己的私有仓库地址和依赖即可。

修改一下入口,执行后能看到打印出了HelloService对象的地址,所以自动配置成功了。

1
2
3
4
5
6
7
8
@SpringBootApplication
public class HelloWorldApplication {

public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(HelloWorldApplication.class, args);
System.out.println(run.getBean(HelloService.class));
}
}

为什么需要 spring.factories

starter为什么要添加 spring.factories 文件?可以试着删掉这个文件,然后添加一个主入口并执行

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
public class StarterDemoApplication {

public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(StarterDemoApplication.class, args);
System.out.println(context.getBean(HelloService.class));
}

}

会发现没有了spring.factories,依旧能打印出HelloService对象的内存地址,自动装配了HelloService实例。

既然如此,为什么还需要这个文件?删掉spring.factories,打一个新jar包,测试项目引入新jar包后,运行后将无法自动装配这个类。具体原理可以看这篇文章spring源码阅读(二)——自动配置