一、SpringBoot starter机制
SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进 starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动 相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自 动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应 用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。
二、为什么要自定义starter
在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放到一个特定 的包下,然后如果另一个工程需要复用这块功能的时候,需要将代码硬拷贝到另一个工程,重新集成一 遍,麻烦至极。如果我们将这些可独立于业务代码之外的功配置模块封装成一个个starter,复用的时候 只需要将其在pom中引用依赖即可,SpringBoot为我们完成自动装配,简直不要太爽。
三、自定义starter的命名规则
SpringBoot提供的starter以 spring-boot-starter-xxx
的方式命名的。官方建议自定义的starter 使用 xxx-spring-boot-starter
命名规则。以区分SpringBoot生态提供的starter
四、开发自定义starter的步骤:
-
1.新建Maven项目,在pom.xml中导入所需要的依赖
-
2.创建xxProperties配置类,写好配置项和默认的配置值,指明配置项前缀,用来读取properties的配置信息
-
3.创建xxService服务类,利用读取的到的资源进行业务操作,所有需要注入xxProperties的对象,通过构造器注入
-
4.创建xxServiceAutoConfiguration自动装配类,使用@Configuration和@Bean来进行自动装配
-
5.在resources中加入spring.factories 配置,指定Starter的自动装配类
五、starter开发示例
下面由我来示范如何开发starter,我将会创建一个文件上传的starter,利用到了org.springframework.web.multipart.MultipartFile
和com.alibaba.fastjson.JSON
1…新建Maven项目,在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.sakura</groupId>
<artifactId>upload-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--加入上传的配置依赖,不需要上传可去除-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--JSON的依赖:不需要JSON可去除-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
<!--自动配置的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<!--配置处理的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.2.2.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
2.创建xxProperties配置类,写好配置项和默认的配置值,指明配置项前缀,用来读取properties的配置信息
package com.sakura.upload;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 配置类
*/
@ConfigurationProperties(prefix = "spring.upload")//配置项前缀
public class UploadProperties {
private String path;//配置项,此处用于指定文件要上传的地址
private String url;//配置项,此处用于指定文件可以被访问的页面路径
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
3.创建xxService服务类,利用读取的到的资源进行业务操作,所有需要注入xxProperties的对象,通过构造器注入
package com.sakura.upload;
import com.alibaba.fastjson.JSON;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* 服务类
*/
public class UploadService {
private UploadProperties uploadProperties;
public UploadService(){
}
public UploadService(UploadProperties uploadProperties){
this.uploadProperties=uploadProperties;
}
/**
* 单文件上传
* @param file
* @return 字符串,文件的访问路径
*/
public String uploadFile(MultipartFile file){
if(!file.isEmpty()){
String name = file.getOriginalFilename();
String end = name.substring(name.lastIndexOf("."));
String start = UUID.randomUUID().toString();
File files=new File(uploadProperties.getPath()+start+end);
try {
file.transferTo(files);
return uploadProperties.getUrl()+start+end;
}catch (Exception e){
e.printStackTrace();
}
}
return null;
}
/**
* 多文件上传
* @param files
* @return json格式的字符串,文件的访问路径
*/
public String uploadFiles2Json(MultipartFile[] files){
if(files.length>0){
List<String> list=new ArrayList<>();
for (MultipartFile file:files) {
if(!file.isEmpty()){
String name = file.getOriginalFilename();
String end = name.substring(name.lastIndexOf("."));
String start = UUID.randomUUID().toString();
File newFile=new File(uploadProperties.getPath()+start+end);
try {
file.transferTo(newFile);
list.add(start+end);
}catch (Exception e){
e.printStackTrace();
}
}
}
String string = JSON.toJSONString(list);
return string;
}
return null;
}
}
4.创建xxServiceAutoConfiguration自动装配类,使用@Configuration和@Bean来进行自动装配
package com.lihui.upload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自动装配类
*/
@Configuration
@EnableConfigurationProperties(UploadProperties.class)
@ConditionalOnClass(UploadService.class)
public class UploadServiceAutoConfiguration {
@Autowired
private UploadProperties uploadProperties;
@Bean
public UploadService uploadService(){
return new UploadService(uploadProperties);
}
}
@ConditionalOnClass:当类路径classpath下有指定的类的情况下进行自动配置
@ConditionalOnMissingBean:当容器(Spring Context)中没有指定Bean的情况下进行自动配置
@ConditionalOnProperty(prefix = “example.service”, value = “enabled”,
matchIfMissing =
true),当配置文件中example.service.enabled=true时进行自动配置,如果没有设置此值就默认使用matchIfMissing对应的值
@ConditionalOnMissingBean,当Spring Context中不存在该Bean时。
@ConditionalOnBean:当容器(Spring Context)中有指定的Bean的条件下
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
@ConditionalOnWebApplication:当前项目是Web项目的条件下
@ConditionalOnResource:类路径下是否有指定的资源
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean
5.在resources中加入spring.factories 配置,指定Starter的自动装配类
注意:META-INF是自己手动创建的目录,spring.factories文件位于resources/META-INF目录下,spring.factories也是手动创建的文件,在该文件中配置自己的自动配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sakura.upload.UploadServiceAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration
后面的类名说明了自动装配类,如果有多个 ,则用逗号分开;
使用者应用(SpringBoot)在启动的时候,会通过org.springframework.core.io.support.SpringFactoriesLoader读取classpath下每个Starter的spring.factories文件,加载自动装配类进行Bean的自动装配;
六、使用自定义starter项目
步骤:
- maven install安装至本地仓库
- 在Spring Boot工程中引入依赖
- 配置Spring Boot工程中的application.properties
到这里,starter项目已经创建完毕,如果想要使用,可以将此starter项目maven install进行打包,这样就可以去使用了
项目想要使用自定义的starter,需要导入依赖,依赖就是starter项目pom.xml中这个位置的代码,如图所示:
<!--自定义starter项目依赖-->
<dependency>
<groupId>com.sakura</groupId>
<artifactId>upload-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
依赖导入之后就可以去配置 application.properties
到这里,你就可以去使用自定义的starter项目了