SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。
在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放到一个特定的包下,然后如果另一个工程需要复用这块功能的时候,需要将代码硬拷贝到另一个工程,重新集成一遍,麻烦至极。如果我们将这些可独立于业务代码之外的功配置模块封装成一个个starter,复用的时候只需要将其在pom中引用依赖即可,SpringBoot为我们完成自动装配.
首先是官方给定的自定义starter命名规则:
SpringBoot提供的starter以spring-boot-starter-xxx
的方式命名的。官方建议自定义的starter使用xxx-spring-boot-starter
命名规则。以区分SpringBoot生态提供的starter。
下面开始代码:
新建一个工程:
依赖如下:
<?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.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wm</groupId>
<artifactId>my-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>my-spring-boot-starter</name>
<description>自定义spring boot start,集成web,lombok</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
定义读取自定义配置属性的类:
package com.wm.myspringbootstarter.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/***
* @ClassName: MyPropertiesConfig
* @Description: 读取配置类属性
* @Author: wm_yu
* @Create_time: 13:57 2020-1-15
*/
@ConfigurationProperties(prefix = "start")
@Data
@Component
public class MyPropertiesConfig {
/**
* 禁用标识
*/
private Boolean enable;
/**
* 内容
*/
private String content;
/**
* 谁说的
*/
private String who;
}
定义一个service,给定方法:
package com.wm.myspringbootstarter.service;
import lombok.AllArgsConstructor;
import lombok.Data;
/***
* @ClassName: TestService
* @Description: 定义一个service
* @Author: wm_yu
* @Create_time: 14:03 2020-1-15
*/
@Data
@AllArgsConstructor
public class TestService {
private String who;
private String content;
public String doSth(){
return String.format("%s say this content is: %s",who,content);
}
}
定义配置类:
package com.wm.myspringbootstarter.config;
import com.wm.myspringbootstarter.service.TestService;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/***
* @ClassName: MyConfig
* @Description:
* @Author: wm_yu
* @Create_time: 14:06 2020-1-15
*/
@Configuration
//只有配置的start.enable为true,这个配置属性类才加载生效
@ConditionalOnExpression("${start.enable:true}")
@AllArgsConstructor
public class MyConfig {
private final MyPropertiesConfig myPropertiesConfig;
@Bean
public TestService testService(){
return new TestService(myPropertiesConfig.getWho(),myPropertiesConfig.getContent());
}
}
下面是定义factories文件:
#-------starter自动装配---------
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wm.myspringbootstarter.config.MyConfig
好了,上面是定义的starter代码,我们将其install到本地仓库
在新建一个项目,应用这个starter:
依赖如下:
<?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.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wm</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入自定义的start依赖-->
<dependency>
<groupId>com.wm</groupId>
<artifactId>my-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
定义cotroller测试类:
package com.wm.demo.controller;
import com.wm.myspringbootstarter.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* @ClassName: TestController
* @Description:
* @Author: wm_yu
* @Create_time: 14:21 2020-1-15
*/
@RestController
@Slf4j
public class TestController {
@Autowired(required = false)
private TestService testService;
@GetMapping("/test")
public String doSth(){
log.info("开始测试.....");
if(ObjectUtils.isEmpty(testService)){
log.info("配置文件中设置为不加载config.....");
return null;
}
String s = testService.doSth();
log.info("调用后的返回值:[{}]",s);
return s;
}
}
在启动类中,扫描当前包及其自定义的starter下的子包:
package com.wm.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.wm")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
假设我们的application.yml没有任何的配置,启动访问:
就是enable为空,也会加载我们的配置类:
下面给定enable为false的情况:
可以看到没有加载配置类的生成
在给定enable为true的情况:
下面说明下@ConditionalOnExpression的使用: