2020-02-29_自定义hello-spring-booter-starter

自定义hello-spring-booter-starter

1概述

1.1 SpringBoot核心原理

springboot的核心有如下四点:

① 起步依赖

核心是依赖传递,官方集成的第三方框架,从而实现版本管理

② 自动配置管理

通过springboot自动配置管理特性将其实例化到(自定义)类中程序启动时,向Spring容器中导入很多配置,代替繁琐的xml或注入Bean。注解中加入EnableConfigurationProperties,application.yml中的所有配置文件都会指向实体类。如server.port对应的实体类ServerProperties(扫描包路径为:org.springframework.boot.autoconfigure),

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)

public class ServerProperties {

③ 运行监控管理Actuator

④ 命令行工具cli

可以使用SpringBoot快速的开发基于Spring框架的项目。由于围绕SpringBoot存在很多开箱即用的Starter依赖,使得我们在开发业务代码时能够非常方便的、不需要过多关注框架的配置,而只需要关注业务即可。

1.2 常用的几个注解说明

@Configuration:表明此类是一个配置类,将变为一个bean被spring进行管理。

@EnableConfigurationProperties:启用属性配置,将读取HelloServiceProperties里面的属性。

@ConditionalOnClass:当类路径下面有HelloServiceConfiguration此类时,自动配置。

@ConditionalOnProperty:判断指定的属性是否具备指定的值。

@ConditionalOnMissingBean:当容器中没有指定bean是,创建此bean。

@ConditionalOnBean:当容器中有指定的Bean的条件下

@ConditionalOnClass:当类路径下有指定的类的条件下

@ConditionalOnExpression:基于SpEL表达式作为判断条件

@ConditionalOnJava:基于JVM版本作为判断条件

@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置

@ConditionalOnMissingBean:当容器中没有指定Bean的情况下

@ConditionalOnMissingClass:当类路径下没有指定的类的条件下

@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下

@ConditionalOnProperty:指定的属性是否有指定的值

@ConditionalOnResource:类路径下是否有指定的资源

@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean @ConditionalOnWebApplication:当前项目是Web项目的条件下

1.3 @EnableAutoC vs @ImportAutoConfiguration

使用@EnableAutoConfiguration时会扫描整个类路径下,包括依赖引入的jar包所有的自动配置类(被注解了@Configuration的类),尝试进行自动配置。比如,tomcat-embedded.jar。

而@ImportAutoConfiguration只运行在你注解中提供的配置类。

下面是一个Spring Boot入口方法中使用@ImportAutoConfiguration的列子:

@ComponentScan("path.to.your.controllers")

@ImportAutoConfiguration({

WebMvcAutoConfiguration.class,

DispatcherServletAutoConfiguration.class,

EmbeddedServletContainerAutoConfiguration.class,

ServerPropertiesAutoConfiguration.class,

HttpMessageConvertersAutoConfiguration.class

})

public class App {

image.png

2自定义boot-starter

遵循springboot官方建议对于非官方的starter命名方式为xxx-spring-boot-starter,所以本工程名为hello-spring-boot-starter。

2.1实现原理

我们知道使用一个公用的starter的时候,只需要将相应的依赖添加的Maven的配置文件当中即可,免去了自己需要引用很多依赖类,并且SpringBoot会自动进行类的自动配置。那么 SpringBoot 是如何知道要实例化哪些类,并进行自动配置的呢,分如下三步骤:

1.SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包,这类似于 Java 的 SPI 机制。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

com.kikop.boot.HelloServiceAutoConfiguration

2.根据spring.factories配置加载AutoConfiguration类。

3.根据 @Conditional注解的条件,进行自动配置并将Bean注入Spring Context 上下文当中。我们也可以使用@ImportAutoConfiguration({HelloServiceAutoConfiguration.class}) 指定自动配置哪些类。

2.2实现步骤

2.2.1创建maven

<?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.kikop.boot</groupId>

<artifactId>hello-spring-boot-starter</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>jar</packaging>

<dependencies>

    <!--业务系统中添加-->

    <!--作用是编译时生成 spring-configuration-metadata.json ,-->

    <!--此文件主要给IDE使用。如当配置此jar相关配置属性在 application.yml ,-->

    <!--你可以用ctlr+鼠标左键点击属性名,IDE会跳转到你配置此属性的类中。-->

    <!--<dependency>-->

        <!--<groupId>org.springframework.boot</groupId>-->

        <!--<artifactId>spring-boot-configuration-processor</artifactId>-->

        <!--<optional>true</optional>-->

    <!--</dependency>-->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-autoconfigure</artifactId>

        <version>2.1.4.RELEASE</version>

    </dependency>

</dependencies>

<build>

    <plugins>

        <plugin>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-maven-plugin</artifactId>

        </plugin>

    </plugins>

</build>

</project>

2.2.2配置文件读取类

package com.kikop.boot.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**

  • @author kikop

  • @version 1.0

  • @project Name: hello-spring-bootstarter

  • @file Name: HelloServiceProperties

  • @desc 功能描述 配置文件读取类

  • 对应yml配置文件总的属性,配置此注解可以自动导入application.properties配置文件中的属性

  • @date 2020/2/20

  • @time 7:33

  • @by IDE: IntelliJ IDEA

*/

@ConfigurationProperties(prefix = HelloServiceProperties.PREFIX,ignoreUnknownFields = true)

public class HelloServiceProperties {

public static final String PREFIX = "com.kikop.boot";

// 定义jar包中默认的配置属性:name

private String name = "hello";

// 定义jar包中默认的配置属性:hobby

private String hobby = "springboot";

// 定义jar包中默认的配置属性:place

private String place="nj";

public String getPlace() {

    return place;

}

public void setPlace(String place) {

    this.place = place;

}

public String getName() {

    return name;

}

public void setName(String name) {

    this.name = name;

}

public String getHobby() {

    return hobby;

}

public void setHobby(String hobby) {

    this.hobby = hobby;

}

}

2.2.3业务实体类

package com.kikop.boot.entity;

import org.springframework.util.StringUtils;

/**

  • @author kikop

  • @version 1.0

  • @project Name: hello-spring-bootstarter

  • @file Name: HelloServiceInfo

  • @desc 功能描述 Starter要实现的功能

  • 已基于业务转化的包装类

  • @date 2020/2/20

  • @time 7:36

  • @by IDE: IntelliJ IDEA

*/

public class HelloServiceInfo {

//姓名

private String name;

//爱好(多个逗号分隔)

private String hobby;

//住址

private String place;

public String getPlace() {

    return place;

}

public void setPlace(String place) {

    this.place = place;

}

public String getName() {

    return "name is " + name;

}

public String getHobby() {

    return "hobby is " + hobby;

}

public void setName(String name) {

    this.name = name;

}

public void setHobby(String hobby) {

    this.hobby = hobby;

}

public String[] split(String separatorChar) {

    return StringUtils.split(this.getHobby(), separatorChar);

}

@Override

public String toString() {

    return "HelloServiceInfo{" +

            "name='" + name + '\'' +

            ", hobby='" + hobby + '\'' +

            ", place='" + place + '\'' +

            '}';

}

}

2.2.4自动配置类

package com.kikop.boot;

import com.kikop.boot.entity.HelloServiceInfo;

import com.kikop.boot.properties.HelloServiceProperties;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

/**

  • @author kikop

  • @version 1.0

  • @project Name: hello-spring-bootstarter

  • @file Name: HelloServiceAutoConfiguration

  • @desc 功能描述 自动配置类

  • @date 2020/2/20

  • @time 7:37

  • @by IDE: IntelliJ IDEA

*/

// 1.Configuration 表明此类是一个配置类,将变为一个bean被spring进行管理

@Configuration

// 2.当类路径下面有HelloServiceInfo此类时,自动配置

@ConditionalOnClass(HelloServiceInfo.class)

// 3.启用属性配置,将读取 HelloServiceProperties 里面的属性

@EnableConfigurationProperties(HelloServiceProperties.class)

//// 4.判断指定的属性是否具备指定的值(放类上)

//@ConditionalOnProperty(prefix = "com.kikop.boot", value = "enabled", matchIfMissing = true)

public class HelloServiceAutoConfiguration {

/**

 * 注入读取的 HelloServiceProperties

 */

@Autowired

private HelloServiceProperties helloServiceProperties;

/**

 * 注入Bean,已基于业务转化的包装类

 * @return

 */

@Bean

@ConditionalOnMissingBean(HelloServiceInfo.class)

// 4.判断指定的属性是否具备指定的值(放Bean上)

// 当配置文件中 com.kikop.boot.enabled=true

@ConditionalOnProperty(prefix = "com.kikop.boot", value = "enabled",matchIfMissing = true)

public HelloServiceInfo helloServiceInfo() {

    HelloServiceInfo helloServiceInfo=new HelloServiceInfo();

    helloServiceInfo.setName(helloServiceProperties.getName());

    helloServiceInfo.setHobby(helloServiceProperties.getHobby());

    helloServiceInfo.setPlace(helloServiceProperties.getPlace());

    return helloServiceInfo;

}

}

2.2.5spring.factories

文件位置:resorces\META-INF\spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

com.kikop.boot.HelloServiceAutoConfiguration

2.3测试

2.3.1加入依赖

<dependency>

<groupId>com.kikop.boot</groupId>

<artifactId>hello-spring-boot-starter</artifactId>

<version>1.0-SNAPSHOT</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-configuration-processor</artifactId>

<optional>true</optional>

</dependency>

2.3.2 controller

@Autowired

HelloServiceInfo helloServiceInfo;

@RequestMapping(value = "/hello")

public String hello() {

return helloServiceInfo.toString();

}

2.3.3 application.yml

com:

kikop:

boot:

enable: true

  name: kikop11

  hobby: tabletennis

  place: nj

2.3.4调用

http://localhost:8762/hello

HelloServiceInfo{name='kikop', hobby='tabletennis', place='nj'}

参考

  1. Springcloud

<u>https://spring.io/projects/spring-cloud</u>

<u>https://start.spring.io/</u>

  1. SpringBoot启动过程分析

<u>https://www.jianshu.com/p/603d125f21b3</u>

  1. SpringBoot启动类图

<u>https://www.processon.com/view/link/59812124e4b0de2518b32b6e</u>

  1. 使用springboot自定义starter实例1

<u>https://blog.csdn.net/qq_21150865/article/details/83504780</u>

  1. 编写自己的SpringBoot-starter

<u>https://www.cnblogs.com/yuansc/p/9088212.html</u>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容