深入浅出自定义创建spring-boot-starter

news2025/1/11 22:57:27

深入浅出自定义创建spring-boot-starter

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration

快速入手

第一步:新建模块
在这里插入图片描述
第二步:修改依赖

<?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">
    <parent>
        <artifactId>microservices</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

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

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

</project>

添加spring-boot-starter和spring-boot-configuration-processor这两个依赖。

第三步:新建Properties配置类

@ConfigurationProperties(prefix = "test")
public class TestProperties {

    /**
     * this is name
     */
    private int name;


    /**
     * this is address
     */
    private String address;

    public int getName() {
        return name;
    }

    public void setName(int name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "TestProperties{" +
                "name=" + name +
                ", address='" + address + '\'' +
                '}';
    }
}

第四步:定义 AutoConfiguration,一个主配置,两个辅配置主要用来验证注解效果。

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "test", value = "enable", havingValue = "true", matchIfMissing = true)
@AutoConfigureAfter({AfterAutoConfiguration.class})
@AutoConfigureBefore({BeforeAutoConfiguration.class})
@EnableConfigurationProperties(TestProperties.class)
public class TestAutoConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(TestAutoConfiguration.class);

    public TestAutoConfiguration(TestProperties properties) {
        logger.info("TEST INIT ...... " + properties.toString());
    }
}
@Configuration
public class AfterAutoConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(BeforeAutoConfiguration.class);

    public AfterAutoConfiguration() {
        logger.info("After INIT ...... ");
    }
}
@Configuration
public class BeforeAutoConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(BeforeAutoConfiguration.class);

    public BeforeAutoConfiguration() {
        logger.info("Before INIT ...... ");
    }
}

第五步:在resources目录下新建META-INF文件夹和spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.starter.config.TestAutoConfiguration, \
com.example.starter.config.BeforeAutoConfiguration, \
com.example.starter.config.AfterAutoConfiguration

整体结构图
在这里插入图片描述
第八步:maven clean install 本地仓库
在这里插入图片描述
第九步:在另一个模块使用starter

        <dependency>
            <groupId>com.example</groupId>
            <artifactId>test-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

第十步:配置yml

test:
  address: abcd
  name: 15

最后:查看效果

c.e.s.config.BeforeAutoConfiguration     : After INIT ...... 
c.e.s.config.TestAutoConfiguration       : TEST INIT ...... TestProperties{name=15, address='abcd'}
c.e.s.config.BeforeAutoConfiguration     : Before INIT ...... 

AutoConfigureAfter和Before

@AutoConfigureAfter({AfterAutoConfiguration.class})
@AutoConfigureBefore({BeforeAutoConfiguration.class})
TestAutoConfiguration 

简称为 A、B、T三个字母。

AutoConfigureAfter 源码注释

Hint for that an auto-configuration should be applied after other specified auto-configuration classes.
当前class 在指定类 后面加载

AutoConfigureBefore源码注释

Hint that an auto-configuration should be applied before other specified auto-configuration classes.
当前class 在指定类 前面加载

根据注释的意思我们得知,T在A后面,T在B前面。所以整个顺序为 A T B。

误区

首先AutoConfigureAfter和AutoConfigureBefore是作用于普通类的,普通的Configure无效。下面我们结合RocketMQAutoConfiguration 的源码来解释这个误区。

@Configuration
@EnableConfigurationProperties(RocketMQProperties.class)
@ConditionalOnClass({MQAdmin.class})
@ConditionalOnProperty(prefix = "rocketmq", value = "name-server", matchIfMissing = true)
@Import({MessageConverterConfiguration.class, ListenerContainerConfiguration.class, 
ExtProducerResetConfiguration.class, ExtConsumerResetConfiguration.class, 
RocketMQTransactionConfiguration.class})
@AutoConfigureAfter({MessageConverterConfiguration.class})
@AutoConfigureBefore({RocketMQTransactionConfiguration.class})

public class RocketMQAutoConfiguration implements ApplicationContextAware {}

依赖图
在这里插入图片描述
spring.factories内容

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration

在RocketMQAutoConfiguration中只有一个自动装配类,MessageConverterConfiguration和RocketMQTransactionConfiguration只是普通的配置类,所以我仿照这种写法实验后,这两个类不会进行加载,源码这里生效的原因是因为@Import(…)这个注解将普通配置类导入,其实这里是没有after和before的效果的,如果不相信可以将spring.factories demo的其余两个自动装配去掉打印控制台输出,然后加入@import注解后在观察输出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/75105.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关键词(三)

关键词一.最冤枉的关键字—sizeof二.“简单”的布尔类型—_Bool一.最冤枉的关键字—sizeof 前面我们说过定义变量是需要空间的&#xff08;声明不需要&#xff09;&#xff0c;同时你需要有类型像int,char…这些不同的类型会在内存中开辟不同大小的空间&#xff0c;而sizeof就可…

Web安全测试工具AppScan简述

01 安全测试的对象 了解常见的Web应用安全漏洞&#xff0c;参考OWASP Top 10 2017。 理解这些常见漏洞的攻击原理&#xff0c;如何判断系统是否存在这些漏洞、如何防止这些漏洞。 02 安全测试的实施 SQL注入测试 确认所有的解释器都明确的将不可信数据从命令语句或者查询语…

微服务囧途之BFF层登场

从单体架构演化为微服务架构后&#xff0c;架构者的期望是“模块A”“模块B” “后端服务”。 场景一 Web端和Mobile端都有一个详情页面&#xff0c;需要调用模块A的getDetail接口获取数据。假设Web端实际需要展示的字段是20个&#xff0c;Mobile端实际需要展示的字段是10个…

记一次Metrics-server异常

报错 前几天测试环境k8s集群做etcd的备份恢复。 所有的pod都起来了&#xff0c;包括metrics-server的状态也是 Running,部署新pod也没有异常&#xff0c;结果kubectl top 请求的时候报错了 Error from server (ServiceUnavailable): the server is currently unable to handle …

Spring cloud Consul 服务注册中心实战

Spring cloud Consul服务注册中心一、简介二、功能三、角色四、工作原理1、服务注册及发现2、服务调用五、起步1、下载2、安装六、实例一、简介 Consul 用于实现分布式系统的服务注册与配置&#xff0c;与其它方案相比&#xff0c;Consul 更 “一站式”&#xff0c;内置了服务…

移植lighttpd笔记

一、前言 lighttpd交叉编译并移植到iTop4412平台 二、编译环境 ubuntu 18.04pcrelighttpd交叉编译链:arm-none-linux-gnueabi三、编译过程 1.pcre交叉编译 tar -xvf pcre-8.38.tar.bz2 cd pcre-8.38/ ./configure --host=arm-none-linux-gnueabi --prefix=/ --enable-utf8 …

IDEA中如何实现 git stash 命令的可视化操作?

目录 问题现象&#xff1a; 问题分析&#xff1a; 拓展&#xff1a;git stash 相关命令 1、git stash 2、git stash save 注释 3、git stash list 4、git stash pop 5、git stash apply stash{编号} 6、git stash drop stash{编号} 7、git stash clear 8、git stash…

flutter 内网安装包生成二维码

参考 前言 有时候我们可能需要用手机访问电脑上的文件, 或者用手机测试电脑上编写的程序 此时 在同一个wifi网络的前提下我们可以这么做: 第一种 使用python 直接使用自带python工具开启http服务, 首先打开终端, 进入需要共享的目录,然后运行以下代码即可: python -m Simple…

React TreeSelect 组件使用和优化

1、自定义折叠和展开图标 此时就要用到switcherIcon属性&#xff0c;以下是antd中对switcherIcon属性的描述&#xff0c; switcherIcon自定义树节点的展开/折叠图标ReactNode | ((props: AntTreeNodeProps) > ReactNode)-具体使用如下&#xff1a; import { DownOutlined…

数据库原理及MySQL应用 | 事件

事件由一个特定的线程——事件调度器来管理&#xff0c;事件是根据指定时间表&#xff0c;在某一特定的时间点&#xff0c;触发相关的SQL语句或存储过程。 01、事件概述 事件(Event)是根据指定时间表执行的任务&#xff0c;是MySQL在相应的时刻调用的过程式数据库对象。它由事…

抓包分析ssh远程主机为何变慢了?

文章目录背景SSH协议握手过程ssh 抓包MAC层包传输tcp握手抓包解释三次握手的第一个报文- SYN包第一个报文对应的抓包详情三次握手的第二个报文- SYNACK包第二个报文对应的抓包详情三次握手的第三个报文- ACK包第三个报文对应的抓包详情ssh版本协议交换密钥协商key阶段Key Excha…

程序员的工资这么高,为什么还会有人离职?

出了社会以后才发现&#xff0c;班级里天天打鸡血的、最奋斗的、同时也最焦虑的&#xff0c;不是成绩最好的&#xff0c;也不是成绩最差的&#xff0c;而是那帮处于中间的人。 他们不像那些成绩最差的&#xff0c;或是天天摆烂&#xff0c;或是靠高情商混得风生水起&#xff1b…

Pytest----pluggy源码解读基础准备

【原文链接】Pytest----pluggy源码解读基础准备 解读pluggy源码&#xff0c;直接使用pytest环境中安装的pluggy即可&#xff0c;比如这里安装的pluggy版本是1.0.0&#xff0c;为了更好的理解源码&#xff0c;这里首先使用如下应用代码作为应用实例&#xff0c;从如下代码中可以…

低代码助力生产管理:离散型制造业MES系统

制造业作为我国国民经济的支柱产业&#xff0c;在我国经济增长中占有主导作用。而制造业对经济增长的贡献很大一部分来自于以离散制造业为代表的机械装备制造、汽车零部件制造等。因此&#xff0c;离散制造业的发展对我国经济增长具有举足轻重的作用。 离散型制造业的特点&…

中创股份在科创板提交上会稿:计划募资6亿元,景新海为董事长

12月8日&#xff0c;山东中创软件商用中间件股份有限公司&#xff08;下称“中创股份”&#xff09;在上海证券交易所科创板提交招股书&#xff08;上会稿&#xff09;。相较于此前招股书&#xff0c;中创股份补充了截至2022年9月30日的财务数据等信息。 据贝多财经了解&#x…

记一次 Eclipse 打包的辛酸历程

文章目录1&#xff1a;背景2 maven 工程3 普通工程3.1 打可执行的 jar3.2 打普通 jar4&#xff1a; 运行 jar 包1&#xff1a;背景 偶然的境况下&#xff0c;被迫使用了 Eclipse 进行代码。遇到的代码也有点奇怪&#xff0c;main 方法启动 java 工程&#xff0c;里面封装 Tomc…

音频声音信号

音频信号是模拟信号&#xff0c;我们需要将其保存为数字信号&#xff0c;才能对语音进行算法操作&#xff0c;WAV是Microsoft开发的一种声音文件格式&#xff0c;通常被用来保存未压缩的声音数据。 通道数&#xff1a;同时有个几个设备在进行音频的采样&#xff1b;采样频率&a…

Django连接MySQL与正反向迁移命令

目录 连接MySQL 方法一&#xff1a;pymysql连接 方法二&#xff1a;mysqlclient 迁移命令 连接MySQL 方法一&#xff1a;pymysql连接 第一步&#xff1a;修改settings.py配置文件中的DATABASES&#xff1a; DATABASES {default: {ENGINE: django.db.backends.mysql,HOS…

【车载开发系列】UDS诊断---动态定义DID($0x2C)

【车载开发系列】UDS诊断—动态定义DID&#xff08;$0x2C&#xff09; UDS诊断---动态定义DID&#xff08;$0x2C&#xff09;【车载开发系列】UDS诊断---动态定义DID&#xff08;$0x2C&#xff09;一.概念定义1&#xff09;DID定义方式2&#xff09;DID失效条件二.应用场景三.报…

【Python游戏】今天小编用Python实现了一个植物大战僵尸小游戏 | 附源码

前言 halo&#xff0c;包子们下午好 今天给打击整一个植物大战僵尸 无广告版本 哈哈 说实话&#xff0c;现在的小游戏很多都是有广告&#xff0c;多少有点难受 今天给大家直接安排 相关文件 关注小编&#xff0c;私信小编领取哟&#xff01; 当然别忘了一件三连哟~~ 源码点…