本文首发于个人网站,原文地址:http://www.javaadu.online/?p=535,如需转载,请注明出处

在学习Spring Boot的过程中,接触最多的就是starter。可以认为starter是一种服务——使得使用某个功能的开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由Spring Boot自动通过classpath路径下的类发现需要的Bean,并织入bean。举个例子,spring-boot-starter-jdbc这个starter的存在,使得我们只需要在BookPubApplication下用@Autowired引入DataSource的bean就可以,Spring Boot会自动创建DataSource的实例。

这里我们会用一个不太规范的starter展示Spring Boot的自动配置的运行原理。Spring Boot的自动配置、Command-line Runner一文中曾利用StartupRunner类在程序运行启动后首先查询数据库中书的数目,现在换个需求:在系统启动后打印各个实体的数量

How Do

  • 新建一个模块db-count-starter,然后修改db-count-starter模块下的pom文件,增加对应的库。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<!-- version继承父模块的-->
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.9.3.RELEASE</version>
</dependency></dependencies>
  • 新建包结构com/test/bookpubstarter/dbcount,然后新建DbCountRunner类,实现CommandLineRunner接口,在run方法中输出每个实体的数量。
package com.test.bookpubstarter.dbcount;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.repository.CrudRepository;
import java.util.Collection; public class DbCountRunner implements CommandLineRunner {
protected final Logger logger = LoggerFactory.getLogger(DbCountRunner.class);
private Collection<CrudRepository> repositories; public DbCountRunner(Collection<CrudRepository> repositories) {
this.repositories = repositories;
}
@Override
public void run(String... strings) throws Exception {
repositories.forEach(crudRepository -> {
logger.info(String.format("%s has %s entries",
getRepositoryName(crudRepository.getClass()),
crudRepository.count()));
});
} private static String getRepositoryName(Class crudRepositoryClass) {
for (Class repositoryInterface : crudRepositoryClass.getInterfaces()) {
if (repositoryInterface.getName().startsWith("com.test.bookpub.repository")) {
return repositoryInterface.getSimpleName();
}
}
return "UnknownRepository";
}
}
  • 增加自动配置文件DbCountAutoConfiguration
package com.test.bookpubstarter.dbcount;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.CrudRepository;
import java.util.Collection; @Configuration
public class DbCountAutoConfiguration {
@Bean
public DbCountRunner dbCountRunner(Collection<CrudRepository> repositories) {
return new DbCountRunner(repositories);
}
}
  • 在src/main/resources目录下新建META-INF文件夹,然后新建spring.factories文件,这个文件用于告诉Spring Boot去找指定的自动配置文件,因此它的内容是
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.test.bookpubstarter.dbcount.DbCountAutoConfiguration
  • 在之前的程序基础上,在顶层pom文件中增加starter的依赖
<dependency>
<groupId>com.test</groupId>
<artifactId>db-count-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
  • 把StartupRunner相关的注释掉,然后在main函数上右键Run BookPubApplication.main(...),可以看出我们编写的starter被主程序使用了。

分析

正规的starter是一个独立的工程,然后在maven中新仓库注册发布,其他开发人员就可以使用你的starter了。

常见的starter会包括下面几个方面的内容:

  1. 自动配置文件,根据classpath是否存在指定的类来决定是否要执行该功能的自动配置。
  2. spring.factories,非常重要,指导Spring Boot找到指定的自动配置文件。
  3. endpoint:可以理解为一个admin,包含对服务的描述、界面、交互(业务信息的查询)
  4. health indicator:该starter提供的服务的健康指标

在应用程序启动过程中,Spring Boot使用SpringFactoriesLoader类加载器查找org.springframework.boot.autoconfigure.EnableAutoConfiguration关键字对应的Java配置文件。Spring Boot会遍历在各个jar包种META-INF目录下的spring.factories文件,构建成一个配置文件链表。除了EnableAutoConfiguration关键字对应的配置文件,还有其他类型的配置文件:

  • org.springframework.context.ApplicationContextInitializer
  • org.springframework.context.ApplicationListener
  • org.springframework.boot.SpringApplicationRunListener
  • org.springframework.boot.env.PropertySourceLoader
  • org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider
  • org.springframework.test.contex.TestExecutionListener

Spring Boot的starter在编译时不需要依赖Spring Boot的库。这个例子中依赖spring boot并不是因为自动配置要用spring boot,而仅仅是因为需要实现CommandLineRunner接口。

两个需要注意的点

  1. @ConditionalOnMissingBean的作用是:只有对应的ban在系统中都没有被创建,它修饰的初始化代码块才会执行,用户自己手动创建的bean优先

  2. Spring Boot starter如何找到自动配置文件(xxxxAutoConfiguration之类的文件)?

  • spring.factories:由Spring Boot触发探测classpath目录下的类,进行自动配置;
  • @Enable:有时需要由starter的用户触发*查找自动配置文件的过程。

Spring Boot 1.x系列

  1. Spring Boot的自动配置、Command-line-Runner
  2. 了解Spring Boot的自动配置
  3. Spring Boot的@PropertySource注解在整合Redis中的使用
  4. Spring Boot项目中如何定制HTTP消息转换器
  5. Spring Boot整合Mongodb提供Restful接口
  6. Spring中bean的scope
  7. Spring Boot项目中使用事件派发器模式
  8. Spring Boot提供RESTful接口时的错误处理实践

本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。

Spring Boot实战之定制自己的starter的更多相关文章

  1. Spring Boot实战之定制URL匹配规则

    本文首发于个人网站:Spring Boot实战之定制URL匹配规则 构建web应用程序时,并不是所有的URL请求都遵循默认的规则.有时,我们希望RESTful URL匹配的时候包含定界符". ...

  2. Spring Boot实战之定制type Formatters

    本文首发于个人网站:Spring Boot实战之定制type Formatters 前面我们有篇文章介绍了PropertyEditors,是用来将文本类型转换成指定的Java类型,不过,考虑到Prop ...

  3. Spring Boot 实战与原理分析视频课程

    Spring Boot 实战与原理分析视频课程 链接:https://pan.baidu.com/share/init?surl=PeykcoeqZtd1d9lN9V_F-A 提取码: 关注公众号[G ...

  4. 《Spring Boot实战》笔记(目录)

    目录 目 录第一部分 点睛Spring 4.x第1 章 Spring 基础 .............................................................. ...

  5. Spring Boot 实战 —— MyBatis(注解版)使用方法

    原文链接: Spring Boot 实战 -- MyBatis(注解版)使用方法 简介 MyBatis 官网 是这么介绍它自己的: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过 ...

  6. spring boot实战(第十三篇)自动配置原理分析

    前言 spring Boot中引入了自动配置,让开发者利用起来更加的简便.快捷,本篇讲利用RabbitMQ的自动配置为例讲分析下Spring Boot中的自动配置原理. 在上一篇末尾讲述了Spring ...

  7. spring boot实战(第十二篇)整合RabbitMQ

    前言 最近几篇文章将围绕消息中间件RabbitMQ展开,对于RabbitMQ基本概念这里不阐述,主要讲解RabbitMQ的基本用法.Java客户端API介绍.spring Boot与RabbitMQ整 ...

  8. 《spring boot 实战》读书笔记

    前言:虽然已经用spring boot开发过一套系统,但是之前都是拿来主义,没有系统的,全面的了解过这套框架.现在通过学习<spring boot实战>这本书,希望温故知新.顺便实现自己的 ...

  9. Spring Boot实战系列-----------邮件发送

    快速导航 添加Maven依赖 配置文件增加邮箱相关配置 Service.Test项目代码构建 五种邮件发送类型讲解 文本邮件 html邮件 附件邮件 html内嵌图片邮件 模板邮件 问题汇总 添加ma ...

随机推荐

  1. JavaScript—字符串(String)用法

    字符串(String)去除空格 str = " hello python " // 去除左空格: str=str.replace( /^\s*/, ''); // 去除右空格: s ...

  2. Java学习笔记(2)--- 对象和类入门,java包,this 和 super区别

    1.对象和类(Object and class): 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作. 面对对象编程是java非常重要的一部分,作者本身之前学过c ...

  3. 《淘宝数据库OceanBase SQL编译器部分 源码阅读--解析SQL语法树》

    淘宝数据库OceanBase SQL编译器部分 源码阅读--解析SQL语法树   曾经的学渣 2014-06-05 18:38:00 浏览1455 云数据库Oceanbase   OceanBase是 ...

  4. Python str & repr

    Python str & repr repr 更多是用来配合 eval 的 (<- 点击查看),str 更多是用来转换成字符串格式的 str() & repr() str() 和 ...

  5. 【ECNU620】数学题(结论题)

    点此看题面 大致题意: 求\((n-1)!\ mod\ n\)的值. 大力猜结论 首先,看到样例,我们可以猜测: 当\(n\)为质数时,答案为\(n-1\). 当\(n\)为合数时,答案为\(0\). ...

  6. 周董新歌搞崩QQ,抓取20W评论看看歌迷在说啥

    9 月 16 日晚间,周董在朋友圈发布了最新单曲<说好不哭> 发布后,真的让一波人哭了 一群想抢鲜听的小伙伴直接泪奔 因为 QQ 音乐直接被搞崩了 没想到干翻 QQ 音乐的不是网易云音乐 ...

  7. [开源]OSharpNS 步步为营系列 - 2. 添加业务数据层

    什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...

  8. 动手学深度学习10- pytorch多层感知机从零实现

    多层感知机 定义模型的参数 定义激活函数 定义模型 定义损失函数 训练模型 小结 多层感知机 import torch import numpy as np import sys sys.path.a ...

  9. LeetCode 94:二叉树的中序遍历 Binary Tree Inorder Traversal

    题目: 给定一个二叉树,返回它的中序 遍历. Given a binary tree, return the inorder traversal of its nodes' values. 示例: 输 ...

  10. windows上mysql解压缩版本、centos上rpm方式的安装、初始化等

    一.windows版本: https://dev.mysql.com/doc/refman/5.7/en/windows-install-archive.html 启动或者暂停mysql服务: htt ...