我们使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中。Starter 为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小伙伴会觉得这个 Starter 好神奇呀!其实 Starter 也都是 Spring + SpringMVC 中的基础知识点实现的,今天松哥就来带大家自己来撸一个 Starter ,慢慢揭开 Starter 的神秘面纱!

核心知识

其实 Starter 的核心就是条件注解 @Conditional ,当 classpath 下存在某一个 Class 时,某个配置才会生效,前面松哥已经带大家学习过不少 Spring Boot 中的知识点,有的也涉及到源码解读,大伙可能也发现了源码解读时总是会出现条件注解,其实这就是 Starter 配置的核心之一,大伙有兴趣可以翻翻历史记录,看看松哥之前写的关于 Spring Boot 的文章,这里我就不再重复介绍了。

定义自己的 Starter

定义

所谓的 Starter ,其实就是一个普通的 Maven 项目,因此我们自定义 Starter ,需要首先创建一个普通的 Maven 项目,创建完成后,添加 Starter 的自动化配置类即可,如下:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>

配置完成后,我们首先创建一个 HelloProperties 类,用来接受 application.properties 中注入的值,如下:

@ConfigurationProperties(prefix = "javaboy")
public class HelloProperties {
private static final String DEFAULT_NAME = "江南一点雨";
private static final String DEFAULT_MSG = "牧码小子";
private String name = DEFAULT_NAME;
private String msg = DEFAULT_MSG;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

这个配置类很好理解,将 application.properties 中配置的属性值直接注入到这个实例中, @ConfigurationProperties 类型安全的属性注入,即将 application.properties 文件中前缀为 javaboy 的属性注入到这个类对应的属性上, 最后使用时候,application.properties 中的配置文件,大概如下:

javaboy.name=zhangsan
javaboy.msg=java

关注类型安全的属性注入,读者可以参考松哥之前的这篇文章:Spring Boot中的yaml配置简介,这篇文章虽然是讲 yaml 配置,但是关于类型安全的属性注入和 properties 是一样的。

配置完成 HelloProperties 后,接下来我们来定义一个 HelloService ,然后定义一个简单的 say 方法, HelloService 的定义如下:

public class HelloService {
private String msg;
private String name;
public String sayHello() {
return name + " say " + msg + " !";
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

这个很简单,没啥好说的。

接下来就是我们的重轴戏,自动配置类的定义,用了很多别人定义的自定义类之后,我们也来自己定义一个自定义类。先来看代码吧,一会松哥再慢慢解释:

@Configuration
@EnableConfigurationProperties(HelloProperties.class)
@ConditionalOnClass(HelloService.class)
public class HelloServiceAutoConfiguration {
@Autowired
HelloProperties helloProperties; @Bean
HelloService helloService() {
HelloService helloService = new HelloService();
helloService.setName(helloProperties.getName());
helloService.setMsg(helloProperties.getMsg());
return helloService;
}
}

关于这一段自动配置,解释如下:

  • 首先 @Configuration 注解表明这是一个配置类。
  • @EnableConfigurationProperties 注解是使我们之前配置的 @ConfigurationProperties 生效,让配置的属性成功的进入 Bean 中。
  • @ConditionalOnClass 表示当项目当前 classpath 下存在 HelloService 时,后面的配置才生效。
  • 自动配置类中首先注入 HelloProperties ,这个实例中含有我们在 application.properties 中配置的相关数据。
  • 提供一个 HelloService 的实例,将 HelloProperties 中的值注入进去。

做完这一步之后,我们的自动化配置类就算是完成了,接下来还需要一个 spring.factories 文件,那么这个文件是干嘛的呢?大家知道我们的 Spring Boot 项目的启动类都有一个 @SpringBootApplication 注解,这个注解的定义如下:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}

大家看到这是一个组合注解,其中的一个组合项就是 @EnableAutoConfiguration ,这个注解是干嘛的呢?

@EnableAutoConfiguration 表示启用 Spring 应用程序上下文的自动配置,该注解会自动导入一个名为 AutoConfigurationImportSelector 的类,而这个类会去读取一个名为 spring.factories 的文件, spring.factories 中则定义需要加载的自动化配置类,我们打开任意一个框架的 Starter ,都能看到它有一个 spring.factories 文件,例如 MyBatis 的 Starter 如下:

那么我们自定义 Starter 当然也需要这样一个文件,我们首先在 Maven 项目的 resources 目录下创建一个名为 META-INF 的文件夹,然后在文件夹中创建一个名为 spring.factories 的文件,文件内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.javaboy.mystarter.HelloServiceAutoConfiguration

在这里指定我们的自动化配置类的路径即可。

如此之后我们的自动化配置类就算完成了。

本地安装

如果在公司里,大伙可能需要将刚刚写好的自动化配置类打包,然后上传到 Maven 私服上,供其他同事下载使用,我这里就简单一些,我就不上传私服了,我将这个自动化配置类安装到本地仓库,然后在其他项目中使用即可。安装方式很简单,在 IntelliJ IDEA 中,点击右边的 Maven Project ,然后选择 Lifecycle 中的 install ,双击即可,如下:

双击完成后,这个 Starter 就安装到我们本地仓库了,当然小伙伴也可以使用 Maven 命令去安装。

使用 Starter

接下来,我们来新建一个普通的 Spring Boot 工程,这个 Spring Boot 创建成功之后,加入我们自定义 Starter 的依赖,如下:

<dependency>
<groupId>org.javaboy</groupId>
<artifactId>mystarter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

此时我们引入了上面自定义的 Starter ,也即我们项目中现在有一个默认的 HelloService 实例可以使用,而且关于这个实例的数据,我们还可以在 application.properties 中进行配置,如下:

javaboy.name=牧码小子
javaboy.msg=java

配置完成后,方便起见,我这里直接在单元测试方法中注入 HelloSerivce 实例来使用,代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UsemystarterApplicationTests { @Autowired
HelloService helloService;
@Test
public void contextLoads() {
System.out.println(helloService.sayHello());
}
}

执行单元测试方法,打印日志如下:

好了,一个简单的自动化配置类我们就算完成了,是不是很简单!

总结

本文主要带领小伙伴自己徒手撸一个 Starter ,使用这种方式帮助大家揭开 Starter 的神秘面纱!大伙有问题可以留言讨论。

本文的案例,松哥已经上传到 GitHub上了,地址:https://github.com/lenve/javaboy-code-samples

关注公众号【江南一点雨】,专注于 Spring Boot+微服务,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!

徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法!的更多相关文章

  1. 【Java面试】如何理解Spring Boot中的Starter?

    一个工作了3年的Java程序员,遇到一个Spring Boot的问题. 他对这个问题有一些了解,但是回答得不是很好,希望参考我的高手回答. 这个问题是:"如何理解Spring Boot中的S ...

  2. Spring Boot2 系列教程(六)自定义 Spring Boot 中的 starter

    我们使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中.Starter 为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小 ...

  3. Spring Boot 中 Druid 的监控页面配置

    Druid的性能相比HikariCp等其他数据库连接池有一定的差距,但是数据库的相关属性的监控,别的连接池可能还追不上,如图: 今天写一下 Spring Boot 中监控页面的配置,我是直接将seat ...

  4. 曹工谈Spring Boot:Spring boot中怎么进行外部化配置,一不留神摔一跤;一路debug,原来是我太年轻了

    spring boot中怎么进行外部化配置,一不留神摔一跤:一路debug,原来是我太年轻了 背景 我们公司这边,目前都是spring boot项目,没有引入spring cloud config,也 ...

  5. Spring Boot2 系列教程(七)理解自动化配置的原理

    Spring Boot 中的自动化配置确实够吸引人,甚至有人说 Spring Boot 让 Java 又一次焕发了生机,这话虽然听着有点夸张,但是不可否认的是,曾经臃肿繁琐的 Spring 配置确实让 ...

  6. Spring Boot中使用EhCache实现缓存支持

     SpringBoot提供数据缓存功能的支持,提供了一系列的自动化配置,使我们可以非常方便的使用缓存.,相信非常多人已经用过cache了.因为数据库的IO瓶颈.一般情况下我们都会引入非常多的缓存策略, ...

  7. Spring Boot中使用缓存

    Spring Boot中使用缓存 随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一. 原始的使 ...

  8. Spring Boot中的缓存支持(一)注解配置与EhCache使用

    Spring Boot中的缓存支持(一)注解配置与EhCache使用 随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决 ...

  9. Spring Boot2 系列教程(十八)Spring Boot 中自定义 SpringMVC 配置

    用过 Spring Boot 的小伙伴都知道,我们只需要在项目中引入 spring-boot-starter-web 依赖,SpringMVC 的一整套东西就会自动给我们配置好,但是,真实的项目环境比 ...

随机推荐

  1. (转)Understanding C parsers generated by GNU Bison

    原文链接:https://www.cs.uic.edu/~spopuri/cparser.html Satya Kiran PopuriGraduate StudentUniversity of Il ...

  2. 01 json方式封装通信接口

    新建一个json_api.php<?php class Response{ /** *按json方式输出通信 *@param integet $code 状态码 *@param string $ ...

  3. 目标检测之harr---角点检测harr 的opencv实现

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187 作者:毛星云(浅墨) ...

  4. 2014年辛星解读css第五节

    本小节我们解说css中的"盒模型".即"box model",它通经常使用于在布局的时候使用,这个"盒模型"也有人成为"框模型&q ...

  5. EF架构~终于自己架构了一个相对完整的EF方案

    EF4.1学了有段时间了,没有静下来好好研究它的架构,今天有空正好把它的架构及数据操作这段拿出来,希望给大家带来帮助,对我自己也是一种总结:P 从图中可以看到,我们用的是MVC3进行程序开发的,哈哈, ...

  6. SQL 游标示例

    DECLARE @i INT ) --给初始值 CREATE TABLE #temp_test --创建临时表 ( num ) ) ) BEGIN INSERT INTO #temp_test ( n ...

  7. 按照eslint 规范写代码 [eslint] 'flag' is assigned to itself. (no-self-assign)

    按照eslint 规范写代码 [eslint] 'flag' is assigned to itself. (no-self-assign)

  8. ChannelHandler揭秘(Netty源码死磕5)

    精进篇:netty源码死磕5  揭开 ChannelHandler 的神秘面纱 目录 1. 前言 2. Handler在经典Reactor中的角色 3. Handler在Netty中的坐标位置 4. ...

  9. codeforces A. Array 解题报告

    题目链接:http://codeforces.com/problemset/problem/300/A 题目意思:给出n个数,将它们分成三批:1.所有数相乘的结果 < 0    2.所有数相乘的 ...

  10. Java NIO(一) 初步理解NIO

    Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式. 为什么要使用 NIO? NIO ...