SpringBoot起飞系列-自定义starter(十)
一、前言
到现在,我们可以看出来,如果我们想用一些功能,基本上都是通过添加spring-boot-starter的方式来使用的,因为各种各样的功能都被封装成了starter,然后把相关服务注入到容器中去,那么如果我们想用一下自己的某些功能呢,那就也要编写一个自定义的starter,所以今天我们就来看看,怎么编写自己的starter,来实现在springboot中实现自己想要的一些功能。
二、原理
回想一下, 当我们使用一个官方的starter的时候,只需要将相应的starter依赖包添加到pom.xml中去就可以了,然后maven自动下载依赖包,并且springboot在启动后会自动配置相关的服务,然后注入的到容器中去。那么springboot是如何知道要去调用哪些方法,加载哪些配置,并注入哪些bean呢?
基本步骤如下:
1.首先,springboot在启动的时候会去找starter包下resources/META-INF/spring.factories文件,然后根据文件中配置的自动配置类运行,加载autoconfigure类。
2.根据@Conditional注解的条件,决定Bean是否要注入的容器中去。
3.然后我们一般用的就是这个Bean,来使用其中的一些功能。
三、编写自己的Starter
3.1 创建maven项目
首先我们创建一个maven项目,按照如下名字起名,其实starter说白了也只是一个jar:

一般的,官方的starter命名方式是spring-boot-start-xxx的形式,为了区分,我们自定义的starter用xxx-spring-boot-starter的命名方式。
1.添加springboot的依赖,因为要成为一个spring-boot-starter是需要依赖springboot的这套流程的,所以我们引入以下依赖:
<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.example.demo</groupId>
<artifactId>person-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.0.0.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies> </project>
2.添加配置类PersonProperties,主要来从配置文件中读取配置绑定到这个类上:
package com.example.demo; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "spring.person")
public class PersonProperties {
private String name; private Integer age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
}
}
3.添加我们的核心服务类,这里边是我们主要提供的功能,假设我们提供了一个sayHello方法,返回一段话:
package com.example.demo;
public class PersonService {
private PersonProperties personProperties;
public PersonService(PersonProperties personProperties) {
this.personProperties = personProperties;
}
public String sayHello() {
return "大家好,我叫: " + personProperties.getName() + ", 今年" + personProperties.getAge() + "岁";
}
}
4.添加自动配置类,这个类主要是给springboot来用的,springboot会用这个类来启动,激活我们的服务,注册都容器中去:
@Configuration
@EnableConfigurationProperties(PersonProperties.class)
@ConditionalOnClass(PersonService.class)
@ConditionalOnProperty(prefix = "spring.person", value = "enabled", matchIfMissing = true)
public class PersonServiceAutoConfiguration {
@Autowired
private PersonProperties personProperties; @Bean
public PersonService personService(){
return new PersonService(personProperties);
}
}
解释一下代码中用到的几个注解:
- @ConditionalOnClass,当classpath下发现该类的情况下进行自动配置。
- @ConditionalOnMissingBean,当Spring Context中不存在该Bean时。
- @ConditionalOnProperty(prefix = "srping.person",value = "enabled",havingValue = "true"),当配置文件中spring.perons.enabled=true时。如果没有,使用matchIfMissing的值,也为true。
- @Bean,把返回的PersonService对象添加的spring容器中去,这样我们再使用的使用就可以直接装配了。
其他注解:
- @ConditionalOnBean:当容器中有指定的Bean的条件下
- @ConditionalOnClass:当类路径下有指定的类的条件下
- @ConditionalOnExpression:基于SpEL表达式作为判断条件
- @ConditionalOnJava:基于JVM版本作为判断条件
- @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
- @ConditionalOnMissingBean:当容器中没有指定Bean的情况下
- @ConditionalOnMissingClass:当类路径下没有指定的类的条件下
- @ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
- @ConditionalOnProperty:指定的属性是否有指定的值
- @ConditionalOnResource:类路径下是否有指定的资源
- @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean
- @ConditionalOnWebApplication:当前项目是Web项目的条件下
5. 在resources下添加spring.factories文件,目录结构如下/resources/META-INF/spring.factories,springboot会自动识别这个文件,加载运行我们的PersonServiceAutoConfiguration类。

6.编译运行,用maven install安装jar,默认会安装的maven的仓库里边,用于后来我们使用。

3.2 创建springboot项目测试
这一步简单就不说了,直接按模板创建一个springboot的web项目就行了,然后我们在pom.xml中添加我们刚才写好的person-spring-boot-starter:
<dependency>
<groupId>com.example.demo</groupId>
<artifactId>person-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
配置文件中添加starter的配置项:
spring.person.age=12
spring.person.name=songlin
添加一个控制器测试:
@RestController
public class HelloController { @Autowired
PersonService personService; @GetMapping("/hello")
public String hello(){
String s = personService.sayHello();
return s;
}
}
访问http://localhost:8080/hello,显示如下:

四、总结
当我们想往springboot集成一个功能的时候,就可以用这种方式了,关于starter的写法,大家还可以参看源码,理解了源码我们就能写出更好用的starter了。springboot的基本入门系列就先到这了,往后我们就开始学习springboot集成高级功能了。
SpringBoot起飞系列-自定义starter(十)的更多相关文章
- SpringBoot起飞系列-Web开发(四)
一.前言 从今天你开始我们就开始进行我们的web开发,之前的一篇用SpringBoot起飞系列-使用idea搭建环境(二)已经说明了我们如何进行开发,当然这是搭建起步,接下来我们就开始进行详细的开发, ...
- SpringBoot起飞系列-国际化(六)
一.前言 国际化这个功能可能我们不常用,但是在有需要的地方还是必须要上的,今天我们就来看一下怎么在我们的web开发中配置国际化,让我们的网站可以根据语言来展示不同的形式.本文接续上一篇SpringBo ...
- SpringBoot起飞系列-配置文件(三)
一.SpringBoot中的配置文件 说起到配置文件,大家并不陌生,早在springboot之前,我们用ssh,ssm框架开发的时候整天都要接触配置文件,那时候的配置文件基本上都是.propertie ...
- SpringBoot起飞系列-入门(一)
一.SpringBoot简介 1.1 什么是SpringBoot 说到spring系列,可能大家都很熟悉,spring.springmvc,美之名曰:spring全家桶,那么springboot其实也 ...
- SpringBoot起飞系列-数据访问(九)
一.前言 前边我们已经学些了开发的基本流程,最重要的一步来了,怎么样和数据库交互才是最重要的,毕竟没有数据那就相当于什么也没做,本文我们来学习使用springboot整合jdbc.mybatis.jp ...
- SpringBoot起飞系列-配置嵌入式Servlet容器(八)
一.前言 springboot中默认使用的是tomcat容器,也叫做嵌入式的servlet容器.因为它和我们平常使用的tomcat容器不一样,这个tomcat直接嵌入到的springboot,平常我们 ...
- SpringBoot起飞系列-拦截器和统一错误处理(七)
一.前言 在前边部分我们已经学会了基本的web开发流程,在web开发中,我们通常会对请求做统一处理,比如未登录的用户要拦截掉相关请求,报错页面统一显示等等,这些都需要配置,可以大大简化我们的代码,实现 ...
- SpringBoot学习(2) - 自定义starter
自己开发一个spring boot starter的步骤1.新建一个项目(全部都基于maven),比如新建一个spring-boot-starter-redis的maven项目 pom.xml: &l ...
- SpringBoot起飞系列-日志使用(四)
一.SpringBoot中的日志组件 日志是一个系统中不可缺少的组件.在项目中,我们常用的日志组件有JUL.JCL.Jboss-logging.logback.log4j.log4j2.slf4j.. ...
随机推荐
- js面向对象学习笔记
1.函数的定义方式 第一种定义方式 function fn1() { alert("fn1"); } alert(fn) 函数就是一个特殊的对象,是一个Function类的实例,其 ...
- 浅谈C语言和C++中“类”的区别
在C语言中,没有“类”的概念,但是可以由结构体struct构造出我们所需要的数据类型,struct可以组合不同的数据类型,可以看作是C语言中的“类”. 下面是C语言中的结构体的实例. #include ...
- 执行jar包或执行其中的某个类
执行jar包,默认执行javafile中指定的main程序java -jar jar包例如 java -jar test.jar执行依赖其他jar包的class: java -cp .;E:\tool ...
- TCP学习
参考 https://coolshell.cn/articles/11564.html https://coolshell.cn/articles/11609.html
- Consider defining a bean of type `xxx` in your configuration问题解决
在使用SpringBoot装配mybatis时出现了异常 *************************** APPLICATION FAILED TO START *************** ...
- DDCTF-2019-writeup(7web+5misc)
一年前第一次参加了DDCTF,再次参加简单记录下web与misc的writeup Web Web1 滴~ 1.jpg参数可以包含文件,参数经过两次base64和一次16进制编码,将index.php编 ...
- js 给元素绑定回车事件
经常会看到登录页面输入完账户密码,回车就登录了.实现方法: JQuery方法: $("#focus")为获取id为focus的元素 $("#focus").ke ...
- 第十四周课程总结&实验报告(简单记事本的实现)
1.JDBC概述 JDBC提供了一种与平台无关的用于执行SQL语句的标准JavaAPI,可以方便的实现多种关系型数据库的统一操作,它由一组用Java语言编写的类和接口组成 主要常用操作类与接口: ja ...
- sentinel控制台监控数据持久化【MySQL】
根据官方wiki文档,sentinel控制台的实时监控数据,默认仅存储 5 分钟以内的数据.如需持久化,需要定制实现相关接口. https://github.com/alibaba/Sentinel/ ...
- C#实现MJPEG服务器
实现流写入,将图像作为mjpeg写入 public class MjpegWriter : IDisposable { , }; , , , }; private string _Boundary; ...