前言
在springboot中,使用的最多的就是starter。starter可以理解为一个可拔插式的插件,例如,你想使用jdbc插件,那么可以使用spring-boot-starter-jdbc;如果想使用mongodb,可以使用spring-boot-starter-data-mongodb。 自定义starter
模式:
启动器只用来做依赖导入;专门来写一个自动配置模块;启动器依赖自动配置;别人只需要引入启动器(starter)
如何编写自动配置
@Configuration //指定这个类是一个配置类
@ConditionalOnXXX //在指定条件成立的情况下自动配置类生效
@AutoConfigureAfter //指定自动配置类的顺序
@Bean //给容器中添加组件
@ConfigurationPropertie //结合相关xxxProperties类来绑定相关的配置
@EnableConfigurationProperties //让xxxProperties生效加入到容器中
自动配置类要能加载
将需要启动就加载的自动配置类,配置在META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
搭建项目
创建一个空项目,然后在此项目中 创建 启动 与 自动配置 模块
编写 自动配置模块
目录结构:
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.cpc</groupId>
<artifactId>cpc-spring-boot-starter-autoconfigurer</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<!--引入spring-boot-starter:所有starter基本配置-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
HelloProperties
分装配置的实体类,我们通过解析这些 xxxProperties 来决定如何配置项目
package com.cpc.starter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "cpc.hello")
public class HelloProperties {
//这里可以通过在配置文件中指定配置来覆盖当前默认的配置,如果不指定那么就会使
///用默认的配置
private String prefix = "我是默认值,如果你不配置的话";
private String suffix;
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}
说明:在使用Spring官方的Starter时通常可以在application.properties中来配置参数覆盖掉默认的值
HelloService
每个starter都有自己的功能,例如在spring-boot-starter-jdbc中最重要的类时JdbcTemplate,每个starter中的核心业务类明白都不同,也没什么规律(像spring-boot-starter-data-xxx的命名是比较有规律的),这里使用HelloService来定义cpc-spring-boot-starter-autoconfigurer
的功能,这里通过一个sayHell
来模拟一个功能。
package com.cpc.starter;
public class HelloService {
HelloProperties helloProperties;
public HelloProperties getHelloProperties() {
return helloProperties;
}
public void setHelloProperties(HelloProperties helloProperties) {
this.helloProperties = helloProperties;
}
public String sayHell(String name) {
return helloProperties.getPrefix() + "-" + name + "-" + helloProperties.getSuffix();
}
}
HelloServiceAutoConfiguration
一般每个starter都至少会有一个自动配置类,一般命名规则使用XxxAutoConfiguration, 例如RedisAutoConfiguration
package com.cpc.starter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnWebApplication//只有web应用才能生效
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
@Autowired
HelloProperties helloProperties;
//将HelloServer组件注册上去
@Bean
@ConditionalOnMissingBean(HelloProperties.class) // 当容器中没有指定Bean的情况下,自动配置HelloProperties类
public HelloService helloService(){
HelloService service = new HelloService();
service.setHelloProperties(helloProperties);
return service;
}
}
• @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
spring.factories
注意:META-INF是自己手动创建的目录,spring.factories也是手动创建的文件,在该文件中配置自己的自动配置类
#这是自动读取配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.cpc.starter.HelloServiceAutoConfiguration
最后打包项目:
使用自定义 starter
直接在 cpc-spring-boot-starter 这个springboot项目用的maven依赖引入好了:
<dependency>
<groupId>com.cpc</groupId>
<artifactId>cpc-spring-boot-starter-autoconfigurer</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
package com.cpc.controller;
import com.cpc.starter.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:
* @Author: cpc
* @Date: 2019-11-09 14:48
* @Version: V1.0
*/
@RestController
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping("/hello")
public String hello(){
return helloService.sayHell("我是用来测试滴");
}
}
在 application.properties
中配置:
#cpc.hello.prefix=my perfix 这里注释掉不配置 perfix 主要是想演示 默认配置的情况
cpc.hello.suffix=my suffix
启动项目测试:
自动配置完成