springboot的每一个starter可以看作是一组依赖的集合,能够作为单独的模块提供特定功能,其实现的思路就是自定义一个工程,根据需求添加相关依赖,然后编写自动配置类,最后打包供其它项目使用。
一、新建maven工程,在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 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.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.test.starter</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>starter</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
其中spring-boot-starter是必须添加的,其它根据实际情况
二、编写配置类
@ConfigurationProperties(prefix = "start.demo")
@Data
public class StartDemoProperties {
private String url = "www.baidu.com";
}
这个类专门存储yml配置文件里的配置,@ConfigurationProperties注解作用是根据prefix的值获取配置文件里的配置并映射到属性上,然后交给spring容器管理
@Configuration
@EnableConfigurationProperties(StartDemoProperties.class)
public class StartDemoConfig {
@Resource
private StartDemoProperties startDemoProperties;
@Bean
@ConditionalOnMissingBean
public HttpClientDemo httpClient() {
HttpClientDemo httpClientDemo = new HttpClientDemo();
httpClientDemo.setUrl(startDemoProperties.getUrl());
return httpClientDemo;
}
}
这个类是实现自动配置的功能,@Configuration注解代表该类是配置类,交给spring容器管理;@EnableConfigurationProperties(StartDemoProperties.class)注解是让括号里的配置类生效;@Bean注解代表该方法返回的bean交给spring容器管理;@ConditionalOnMissingBean注解代表返回的bean不存在时才生效
贴一下demo功能类HttpClientDemo的代码
@Data
public class HttpClientDemo {
private String url;
public String getHtml() {
try {
URL url = new URL(this.url);
URLConnection urlConnection = url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "错误";
}
}
三、资源文件配置
在resources目录下新建文件夹META-INF,在该文件夹下新建名字为spring.factories的文件,这个文件的值是以键值形式存储的
EnableAutoConfiguration就是springboot特有的自动配置类,值为自定义编写的配置类
四、打包使用
使用maven的import命令将该项目打包并安装到本地仓库,或者提交到远程私服,在其它项目使用时只需要添加依赖即可
五、扩展
springboot是如何实现这些自动配置呢?
springboot的启动类有一个注解:
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
它是@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan的组合注解,exclude属性代表排除某个自动配置类
@SpringBootConfiguration代表该类是springboot的配置类
@ComponentScan是spring的自动扫描
@EnableAutoConfiguration是核心注解,表示自动配置
@EnableAutoConfiguration分析
该注解内部使用了@Import({AutoConfigurationImportSelector.class}),这个注解会导入AutoConfigurationImportSelector.class类,正是这个类实现了自动配的的功能,该类的selectImports()方法是执行入口,调用getAutoConfigurationEntry()方法获取自动配置,其中的getCandidateConfigurations()方法调用了spring的SpringFactoriesLoader.loadFactoryNames()方法来获取项目下所有Jar包的spring.factories文件里的配置类,然后排除掉exclude属性设置的类