封面画师:adsuger 封面ID:77171064
1. SpringBoot 原理
参考链接:Spring Boot参考指南
1.1 Hello World
-
使用 IDEA 创建 SpringBoot 项目:
- 选择 spring initalizr,可以看到默认就是去官网的快速构建工具实现的
- 填写项目信息
- 选择初始化组件(初学选择 Web 即可)
- 填写项目路径,等待项目构建完成
-
项目结构分析:
- 程序的主启动类
xxxxxxxApplication.java - 一个 application.properties 配置文件
- 一个 测试类
- 一个 pom.xml
- 程序的主启动类
-
编写一个 http 接口
-
在主程序的同级目录下,新建一个 controller 包。注意:一定要在同级目录下,否则会识别不到
-
在创建的 controller 包下新建一个 HelloController 类:
@RestController public class HelloController { @RequestMapping("/hello") public String hello() { return "Hello World"; } } -
编写完毕后,从主程序启动项目,浏览器发起请求,看页面返回;控制台输出了 Tomcat 访问的端口号!
-
-
彩蛋:自定义 banner 图案
- 到项目下的 resources 目录下新建一个 banner.txt 文件
- 将图案拷贝到文件中即可
1.2 运行原理初探
2.1 启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- spring-boot-starter-xxx:就是 Springboot 的场景启动器
- spring-boot-starter-web:帮助我们导入 web 模块正常运行所依赖的组件
- 作用:Springboot 将所有的场景抽取出来,做成了一个个启动器(starter),只需要在项目中引入启动器即可,所有的依赖都会导入进来。我们只需要选择我们自己需要的启动器,同时我们还可以自定义启动器
2.2 主启动类
@SpringBootApplication //使用SpringBootApplication来标注这是一个主程序类
//说明这是一个Springboot应用
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
//run方法不仅启动了一个方法,还启动了一个服务
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
2.3 注解分析
2.3.1 @SpringBootApplication
-
作用: 标注在某个类上说明这个类是 SpringBoot 的主配置类,SpringBoot 就应该运行这个类的 main 方法来启动 SpringBoot 应用;启动类下的所有资源被导入
-
点击进入这个注解,可以查看到其他很多注解:
- @ComponentScan、@SpringBootConfiguration、 @EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = { @Filter(
type = FilterType.CUSTOM,
classes = TypeExcludeFilter.class
),@Filter(
type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//......
}
2.3.2 @ComponentScan
- Spring 内主要注解,它对应 XML 配置中的
<context:component-scan base-package="xxx" />元素 - 作用: 自动扫描并加载符合条件的组件或者 bean,将这个 bean 定义加载到 IOC 容器中
2.3.3 @SpringBootConfiguration
-
作用: SpringBoot 的配置类。标注在某个类上,表示这是一个 SpringBoot 的配置类
-
继续点击进入这个注解:
@Configuration
public @interface SpringBootConfiguration {...}
//点击进入Configuration
@Component
public @interface Configuration {...}
- 分析:
- @Configuration 表明这是配置类,配置类就是对应 Spring 的 xml 配置文件
- @Component 说明启动类本身也是 Spring 中的一个组件而已,负责启动应用
回到@SpringBootApplication 注解中,查看@EnableAutoConfiguration 注解
2.3.4 @EnableAutoConfiguration
- 作用: 开启自动配置功能。以前的一些框架的配置需要我们手动配置,现在 SpringBoot 可以自动帮我们配置。而@SpringBootApplication 可以开启 SpringBoot 的自动配置功能,这样自动配置才可以生效
点击进入@EnableAutoConfiguration 注解:
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {...}
- @AutoConfigurationPackage:自动配置包
点击进入@AutoConfigurationPackage 注解:
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
@import :Spring 底层注解@import,给容器中导入一个组件。
Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到 Spring 容器。
- @Import(AutoConfigurationImportSelector.class):给容器导入组件
AutoConfigurationImportSelector:自动配置导入选择器。那么它会导入哪些组件的选择器呢?
点击进入 AutoConfigurationImportSelector 类:
- 这个类中有这样的一个方法:
//获得候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
/**getSpringFactoriesLoaderFactoryClass()方法
* 返回的是启动自动导入配置文件的注解类:EnableAutoConfiguration
*/
List<String> configurations =
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
//getSpringFactoriesLoaderFactoryClass()方法
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
- 这个方法又调用了 SpringFactoriesLoader 类的静态方法,进入 SpringFactoriesLoader 类中 loadFactoryNames() 方法:
public static List<String> loadFactoryNames(Class<?> factoryType,
@Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
//此处调用了loadSpringFactories()方法
return loadSpringFactories(classLoader).getOrDefault(
factoryTypeName, Collections.emptyList());
}
- 点击 loadSpringFactories() 方法进行查看:
private static Map<String, List<String>> loadSpringFactories(
@Nullable ClassLoader classLoader) {
//获得classLoader,这里得到的就是EnableAutoConfiguration标注的类本身
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
//public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
//获取一个资源 "META-INF/spring.factories"
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
//将读到的资源遍历,封装成一个properties
while (urls.hasMoreElements()) { //判断有没有更多的元素
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
- 在这个类中我们发现了多次出现的文件:spring.factories,进行全局搜索

- 打开这个文件我们可以看到很多自动配置的文件,而这就是自动配置根源的所在

- 在这些配置文件中我们选取一个我们熟悉的配置类打开,比如:WebMvcAutoConfiguration

我们可以看到这些都是一个个的 JavaConfig 配置类,同时注入了一些 Bean。
所以,自动配置真正实现是从 classpath 中搜寻所有的 META-INF/spring.factories 配置文件,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration 的 JavaConfig 形式的 IoC 容器配置类,然后将这些都汇总成为一个实例并加载到 IoC 容器中。
自动装配的核心: 可以用 JavaConfig 类取代 xml 配置,并可以用 yaml 文件对 JavaConfig(标记@ConfigProperties)类的属性进行修改。
- 思考: 这么多的自动配置为什么有些没有生效而需要导入对应的 starter 才有作用?
我们没有导入 AOP 的相关依赖,所以我们找到 AOP 的自动配置并打开:

打开后我们会发现有这样一个注解:

我们可以看到,@ConditionalOnClass 注解爆红!这是为什么?
答案很简单,因为我们没有导入 AOP 相关的依赖,我们需要导入依赖(对应的 starter)后这个注解才不会爆红,而只有这个注解不爆红,SpringBoot 的 AOP 自动配置才会生效。
@ConditionalOnxxxx:只有里面的条件都满足,自动配置才会生效。
- 结论:
- SpringBoot 在启动的时候从类路径下的 META-INF/
spring.factories中获取 EnableAutoConfiguration 指定的值,将这些值作为自动配置类导入容器,自动配置类就会生效,帮我们进行自动配置的工作 - 整个 J2EE 的整体解决方案和自动配置都在 springboot-autoconfigure 的 jar 包中,它将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中
- 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入了某一场景需要的所有组件,并配置好这些组件。我们有了自动配置类,免去了我们手动编写配置注入功能组件等的工作
- SpringBoot 在启动的时候从类路径下的 META-INF/
理一下注解:

到此,我们就大概的了解了 SpringBoot 的运行原理!
2.4 SpringApplication.run
- 该方法主要有两部分,一部分是 SpringApplication 的实例化,二是 run 方法的执行
- SpringApplication 类主要做了一下四件事:
- 推断应用的类型是普通的项目还是 Web 项目
- 查找并加载所有可用初始化器,设置到 initializers 属性中
- 找出所有的应用程序监听器,设置到 listeners 属性中
- 推断并设置 main 方法的定义类,找到运行的主类
构造器:
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
// ......
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances();
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
1.3 yaml 配置注入
3.1 基本语法
- application.yml
- 语法结构:key: 空格 value
server:
port: 8081
-
说明:语法要严格要求!
- 空格不能省略
- 以缩进控制层级关系
- 属性和值的大小写都是十分敏感的
-
引号的使用:
-
「 」 双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
比如:name: “mo \n fan” 输出:mo 换行 fan
-
” 单引号,会转义特殊字符,特殊字符最终会变成和普通字符一样输出
比如:name: ‘mo \n fan’ 输出:mo \n fan
-
3.2 其他语法
- 对象、Map 键值对
k:
v1:
v2:
行内写法:
person: {name: mofan, age: 18}
注意缩进和空格
- 数组集合(List、Set)
person:
- student
- teacher
- doctor
行内写法:
person: [student,teacher,doctor]
3.3 配置文件注入
当我们需要给实体类注入匹配值时,根据 Spring 的学习,我们可以:使用@Component 将 bean 注册到容器中,然后使用@Value 注解给 bean 的每个属性注入值。现在我们还可以用 yaml 配置的方式进行注入:
- 首先编写一个实体类,Person 类
/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
@Component //注册bean
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
//有参无参构造、get、set方法、toString()方法
}
- 编写一个 yaml 配置:
person:
name: mofan
age: 18
happy: true
birth: 2000/01/01
maps: {k1: v1,k2: v2}
lists:
- game
- music
dog:
name: 小黑
age: 3
然后我们在 SpringBoot 的测试类中编写测试即可。
@Autowired
private Person person;
void contextLoads(){
System.out.println(person);
}
- 如果 IDEA 提示:SpringBoot 配置注解处理器没有找到,那么需要我们添加一个依赖。
<!--导入依赖后需要重启-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
-
注意:
- 如果配置文件的 key 值和属性值设置不一样,则输出结果会为 null,表示注入失败。
- 注意注解@ConfigurationProperties 的使用。@configurationProperties:默认从全局配置文件中获取值。
- 如果存在多个配置文件(比如还存在一个 person.properties 文件),这时我们进行注入并想要绑定这个配置文件时,可以使用 @PropertySource 注解来加载指定的配置文件。
@PropertySource(value = "classpath:person.properties") @Component public class Person { @Value("${name}") private String name; ... }- 使用 yaml 配置文件还可以编写占位符。如:
person: name: mofan${random.uuid} # 随机 uuid age: ${random.int} # 随机 int ... dog: name: ${person.hello:other}_小黑 age: 3- 如果我们需要使用 properties 配置,在配置文件中书写中文时,IDEA 会出现乱码,需要我们进行设置。settings—>FileEncodings —>设置编码格式为 UTF-8(把旁边的勾打上)。
3.4 yaml总结
- @ConfigurationProperties 和@Value 对比:
| @ConfigurationProperties | @Value | |
|---|---|---|
| 功能 | 批量注入配置文件中的属性 | 一个一个地指定属性值 |
| 松散绑定 | 支持 | 不支持 |
| SpEL | 不支持 | 支持 |
| JSR303 校验 | 支持 | 不支持 |
| 复杂类型封装 | 支持 | 不支持 |
- 松散绑定:比如我的 yml 中写的 last-name,这个和 lastName 是一样的,- 后面跟着的字母默认是大写的
- JSR303 数据校验,这个就是我们可以在字段是增加一层过滤器验证,可以保证数据的合法性
- yaml 可以封装对象,而 value 不行
- 总结:
- 如果配置 yaml 和配置 properties 都可以获取到值,推荐 使用 yaml
- 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value
- 如果我们专门编写了一个 JavaBean 来和配置文件进行一一映射,直接使用@ConfigurationProperties
1.4 JSR303 数据校验
- 使用:在 SpringBoot 中使用@Validated 注解来校验数据,如果数据处在异常,则会抛出异常,方便统一处理。比如,我们可以写一个注解使我们的 name 属性不能为空:
@Component //注册bean
@ConfigurationProperties(prefix = "person")
@Validated //数据校验
public class Person {
@NotNull(message="名字不能为空")
private String name;
}
如果这时 name 为空,则会抛出异常,并显示设置的 default message。
- 常见参数:
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) string is between min and max included.
日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则
等等...
我们也可以自定义一些校验规则
1.5 多环境切换
5.1 多配置文件
- 我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml , 用来指定多个环境版本
例如:
application-test.properties:测试环境配置
application-dev.properties:开发环境配置
但是 Springboot 并不会直接启动这些配置文件,它 默认使用 application.properties 主配置文件,我们需要通过一个配置来选择需要激活的环境:
#比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试;
#我们启动SpringBoot,就可以看到已经切换到dev下的配置了;
spring.profiles.active=dev
5.2 yaml多文档块
- 同样可以使用 yaml 配置文件实现多环境切换,但是使用 yaml 可以不需要创建多个配置文件,比如:
server:
port: 8081
#选择要激活那个环境块
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev #配置环境的名称
---
server:
port: 8084
spring:
profiles: prod #配置环境的名称
- 注意:
- 使用 yaml 的多文档块时,需要指明环境名称,文档快之间用「---」隔开
- 如果 yml 和 properties 同时都配置了端口,并且没有激活其他环境,默认会使用 properties 配置文件的!
5.3 配置文件加载顺序
- SpringBoot 启动会扫描一下位置的 application.properties 或者 application.yml 文件作为 Spring boot 的默认配置文件:
优先级1:file:./config/ 项目路径下的config文件夹配置文件
优先级2:file:./ 项目路径下配置文件
优先级3:classpath:/config/ 资源路径下的config文件夹配置文件
优先级4:classpath:/ 资源路径下配置文件
优先级由高到低,高优先级的配置会覆盖低优先级的配置。SpringBoot 会从这四个位置全部加载主配置文件,互补配置。
1.6 自动装配原理
- 思考: 经过编写 yaml 配置文件的学习,我们认识到可以使用 yaml 配置文件设置相关配置,但是配置文件到底该怎么写?又能写些什么?
6.1 原理分析
我们在 2. 运行原理初探 中已经找到了文件 spring.factories 所处的位置,
这时我们可以选取 HttpEncodingAutoConfiguration(Http 编码自动配置) 为例解释自动配置原理:
//表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件
@Configuration
//启动指定类的ConfigurationProperties功能
//进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来
//并把HttpProperties加入到ioc容器中
@EnableConfigurationProperties({HttpProperties.class})
//Spring底层@Conditional注解
//根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效
//这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(
type = Type.SERVLET
)
//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器
@ConditionalOnClass({CharacterEncodingFilter.class})
//判断配置文件中是否存在某个配置:spring.http.encoding.enabled
//如果不存在,判断也是成立的
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的
@ConditionalOnProperty(
prefix = "spring.http.encoding",
value = {"enabled"},
matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
//他已经和SpringBoot的配置文件映射了
private final Encoding properties;
//只有一个有参构造器的情况下,参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this.properties = properties.getEncoding();
}
//给容器中添加一个组件,这个组件的某些值需要从properties中获取
@Bean
@ConditionalOnMissingBean //判断容器没有这个组件?
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
return filter;
}
//......
}
简单总结:SpringBoot 根据当前不同的条件判断,决定这个配置文件是否生效。
- 一但这个配置类生效,这个配置类就会给容器中添加各种组件
- 这些组件的属性是从对应的 properties 类中获取的,这些类里面的每一个属性又是和配置文件绑定的
- 所有在配置文件中能配置的属性都是在 xxxxProperties 类中封装着
- 配置文件能配置什么就可以参照某个功能对应的这个属性类
点击进入 HttpProperties.class:
//从配置文件中获取指定的值和bean的属性进行绑定
@ConfigurationProperties(prefix = "spring.http")
public class HttpProperties {
//....
}
然后我们可以在配置文件中进行 httpencoding 的相关配置,并进行对比:

到此,我们就明白了自动装配的核心!
6.2 原理总结
-
SpringBoot 启动会加载大量的自动配置类
-
我们判断我们需要的功能有没有在 SpringBoot 默认写好的自动配置类当中;
-
我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件存在在其中,我们就不需要再手动配置了);
-
给容器中自动配置类添加组件的时候,会从 properties 类中获取某些属性,我们只需要在配置文件中指定这些属性的值即可。
-
两大注解:
-
xxxxAutoConfigurartion:自动配置类,给容器中添加组件
-
xxxxProperties:封装配置文件中相关属性;
-
6.3 @Conditional
- SpringBoot 的自动装配类必须在一定的条件下才能生效,SpringBoot 用到了 @Conditional 派生注解
- 作用:必须是@Conditional 指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效。
| @Conditional 拓展注解 | 作用(判断是否满足当前指定条件) |
|---|---|
| @ConditionalOnJava | 系统的 Java 版本是否符合要求 |
| @ConditionalOnBean | 容器中存在指定的 Bean |
| @ConditionalOnMissingBean | 容器中不存在指定的 Bean |
| @ConditionalOnExpression | 满足 SpEL 表达式的指定 |
| @ConditionalOnClass | 系统中有指定的类 |
| @ConditionalOnMissingClass | 系统中没有指定的类 |
| @ConditionalOnSingleCandidate | 容器中只有一个指定的 Bean,或者这个 Bean 是首选 Bean |
| @ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
| @ConditionalOnResource | 类路径下是否存在指定的资源文件 |
| @ConditionalOnWebApplication | 当前是 Web 环境 |
| @ConditionalOnNotWebApplication | 当前不是 Web 环境 |
| @ConditionalOnJndi | JNDI 存在指定项 |
- 如此多的自动配置类必须在满足了指定条件下才会生效,那么我们怎么知道哪些自动配置生效了呢?
我们可以通过启用 debug=true 属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;
#开启springboot的调试类
debug=true
控制台会输出三大项:
Positive matches:(自动配置类启用的:正匹配)
Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)
Unconditional classes: (没有条件的类)
1.7 自定义 Starter
我们先明白 Starter 的一些基础知识:
-
启动器模块是一个 空 jar 文件,仅提供辅助性依赖管理,这些依赖可能用于自动装配或者其他类库
-
命名规约:
官方命名:
- 前缀:spring-boot-starter-xxx
- 比如:spring-boot-starter-web…
自定义命名:
- xxx-spring-boot-starter
- 比如:mybatis-spring-boot-starter
明白命名规约有助于帮助我们命名自定义启动器。
7.1 编写启动器
- 在 IDEA 中新建一个空项目 spring-boot-starter-diy;
- 完成第一步后,新建一个普通 Maven 模块:yang-spring-boot-starter

- 新建一个 Springboot 模块:yang-spring-boot-starter-autoconfigure
- 新建好两个 Module 后,基本结构为

- 在我们的 starter 中 导入 autoconfigure 的依赖:
<!-- 启动器 -->
<dependencies>
<!-- 引入自动配置模块 -->
<dependency>
<groupId>com.yang</groupId>
<artifactId>yang-spring-boot-starter-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
-
将 autoconfigure 项目下多余的文件都删掉,Pom 中只留下一个 starter,这是所有的启动器基本配置
注意:记得将 test 目录也删除,否则会安装到 maven 仓库时会失败!

- 编写我们自己的服务:
/**
* @author Mofan_Yang
*/
public class HelloService {
HelloProperties helloProperties;
public HelloProperties getHelloProperties() {
return helloProperties;
}
public void setHelloProperties(HelloProperties helloProperties) {
this.helloProperties = helloProperties;
}
public String sayHello(String name){
return helloProperties.getPrefix() + name + helloProperties.getSuffix();
}
}
- 编写 HelloProperties 配置类:
/**
* @author Mofan_Yang
*/
// 设置前缀 yang.hello
@ConfigurationProperties(prefix = "yang.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;
}
}
- 编写自动配置类并注入 bean:
/**
* @author Mofan_Yang
*/
@Configuration
@ConditionalOnWebApplication //web应用生效
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
@Autowired
HelloProperties helloProperties;
@Bean
public HelloService helloService(){
HelloService service = new HelloService();
service.setHelloProperties(helloProperties);
return service;
}
}
- 在 resources 编写一个自己的 META-INF\spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yang.HelloServiceAutoConfiguration
- 编写完成后,安装到 Maven 仓库
注意: 代码只在 yang-spring-boot-starter-autoconfigure 中编写,启动器 Starter 中没有任何代码。
7.2 测试Starter
- 新建一个 SpringBoot 项目;
- 导入我们自定义的启动器:
<dependency>
<groupId>com.yang</groupId>
<artifactId>yang-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- 编写一个 HelloController 控制器,测试自定义的启动器:
@RestController
@RequestMapping("/test")
public class HelloController {
@Autowired
HelloService helloService;
@RequestMapping("/hello")
public String hello(){
return helloService.sayHello("我是内容 ");
}
}
- 编写配置文件 application.yml
yang:
hello:
prefix: "我是前缀 "
suffix: "我是后缀 "
- 启动项目测试,查看结果

自定义启动器编写成功!