持续原创输出,点击上方蓝字关注我

前言

日常工作中对于Spring Boot 提供的一些启动器可能已经足够使用了,但是不可避免的需要自定义启动器,比如整合一个陌生的组件,也想要达到开箱即用的效果。

在上一章节从底层源码介绍了Spring Boot 的自动配置的原理,未读过的朋友建议看一下:Spring Boot 自动配置源码解析

这篇文章将会介绍如何自定义一个启动器,同时对于自动配置类的执行顺序做一个详细的分析。

如何自定义一个starter?

启动器的核心其实就是自动配置类,在自动配置源码分析的章节已经介绍过,AutoConfigurationImportSelector是从spring.factories中加载自动配置类,因此只需要将自定义的自动配置类设置在该文件中即可。

读过源码的朋友都知道自动配置类常用的一些注解,总结如下:

  1. @Configuration: 该注解标志这是一个配置类,「自动配置类可以不加该注解」
  2. @EnableConfigurationProperties:这个配置也是经常使用了,使得指定的属性配置生效。一般自动配置类都需要从全局属性配置中读取自定义的配置,这就是一个开关。
  3. @ConditionalOnXxxx:该注解是自动配置类的核心了,自动配置类既要启动时自动配置,又要保证用户用户自定义的配置覆盖掉自动配置,该注解就是一个条件语句,只有当指定条件成立才会执行某操作。不理解的,请看作者前面的一篇文章:这类注解都不知道,还说用过Spring Boot~
  4. @AutoConfigureAfter:指定自动配置类的执行先后顺序,下文详细介绍。
  5. @AutoConfigureBefore:指定自动配置列的执行先后顺序,下文详细介绍。
  6. @AutoConfigureOrder:指定自动配置类的优先级,下文详细介绍。

有了以上准备,自定义一个starter非常简单,分为两个步骤。

1. 准备自己的自动配置类

启动器的灵魂核心就是自动配置类,因此需要首先创建一个自动配置类,如下:

@Configuration
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE+5)
@ConditionalOnProperty(prefix = "my.auto",name = "enabled",havingValue = "true",matchIfMissing = true)
public class MyCustomAutoConfiguration {

}

以上自动配置类只是作者简单的按照格式随手写了一个,真实开发中需要根据启动器的业务做默认配置。

2. 将自动配置类设置在spring.factories

标注了@Configuration注解的自动配置类如果不放在spring.factories文件中,仅仅是一个普通的配置类而已。想要其成为自动配置类,需要在spring.factories文件中设置,如下:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.MyCustomAutoConfiguration

经过以上的配置,粗略的启动器完成了,只需要打包,然后Maven引入即可工作。

如何指定自动配置类的执行顺序?

自动配置类需要定义执行顺序吗?答案:肯定的。比如Mybatis的自动配置类,肯定要在数据源的自动配置类之后执行,否则如何创建SqlSessionFactory

如何自定义自动配置类的执行顺序呢?此时就需要用到上文提到的三个注解,如下:

  1. @AutoConfigureAfter: 当前配置类在指定配置类之后执行
  2. @AutoConfigureBefore: 当前配置类在指定配置类之前执行
  3. @AutoConfigureOrder:指定优先级,数值越小,优先级越高。

分享一个经典的误区

对于Spring Boot不是很了解的人写出的代码真是「不堪入目」,曾经看过有人在「普通的配置类」上使用@AutoConfigurexxx注解,如下;

@Configuration
@AutoConfigureBefore(Config2.class)
public class Config1{}

@Configuration
public class Config2{}

是不是感觉很爽,原来还能这么指定配置类的执行顺序.....(此处省略一万字)

可能有时候走了狗屎运给你一种错觉还真的配置成功了。实际上这种方式是不可行的,以上三个注解只有针对自动配置类才会生效。

源码分析自动配置类如何排序?

其实关键的代码还是在AutoConfigurationImportSelector中,将自动配置类从spring.factories加载出来之后会根据条件排序,在selectImports()方法中最后一行代码如下:

return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
     .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
     .collect(Collectors.toList());

上面的代码则是将排序好的自动配置类返回,跟进代码,发现最终的实现都在AutoConfigurationSorter.getInPriorityOrder()方法中,逻辑如下图:

具体的流程如上图,排序也是按照先后顺序,如下:

  1. 先按照字母排序
  2. 按照@AutoConfigureOrder优先级排序
  3. 最终按照@AutoConfigureAfter@AutoConfigureBefore排序

从上面配置的顺序可以知道,最终决定权还是在@AutoConfigureAfter@AutoConfigureBefore这两个注解。

总结

本文介绍了如何自定义一个启动器以及指定自动配置类的执行顺序,通过作者的介绍,希望读者们能够理解并灵活运用。

另外作者的第一本PDF书籍已经整理好了,由浅入深的详细介绍了Mybatis基础以及底层源码,有需要的朋友公号回复关键词「Mybatis进阶」即可获取,目录如下:

头秃了,使用@AutoConfigureBefore指定配置类顺序竟没生效?的更多相关文章

  1. 使用@AutoConfigureBefore调整配置顺序竟没生效?

    一个人的价值体现在能够帮助多少人.自己编码好,价值能得到很好的体现.若你做出来的东西能够帮助别人开发,大大减少开发的时间,那就功德无量. 作者:A哥(YourBatman) 公众号:BAT的乌托邦(I ...

  2. 使用配置类而不使用XML文件(代替bean.xml)对spring进行配置

    以下类是一个配置类,它的作用和bean.xml是一样的注解: @Configuration 作用: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解. 获取容器时需要使用Anno ...

  3. 配置类需要标注@Configuration却不知原因?那这次就不能给你涨薪喽

    专注Java领域分享.成长,拒绝浅尝辄止.关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.My ...

  4. 头秃了,Spring Boot 自动配置了解一波~

    持续原创输出,点击上方蓝字关注我 目录 前言 源码版本 @SpringBootApplication干了什么? @EnableAutoConfiguration干了什么? 总结 前言 为什么Sprin ...

  5. 在Struts.xml中的result元素指的是:指定动作类的动作方法执行完后的结果视图.

    result结果集 上一篇文章主要讲Struts2框架(4)---Action类访问servlet这篇主要讲result结果集 在Struts.xml中的result元素指的是:指定动作类的动作方法执 ...

  6. Spring boot 配置文件参数映射到配置类属性

    [参考文章]:SpringBoot之@EnableConfigurationProperties分析 [参考文章]:在Spring Boot中使用 @ConfigurationProperties 注 ...

  7. Hibernate api 之常见的类(配置类,会话工厂类,会话类)

    1:Configuration :配置管理类对象 1.1:config.configure(): 加载主配置文件的方法(hibernate.cfg.xml) ,默认加载src/hibernate.cf ...

  8. springboot的yaml基础语法与取值,配置类,配置文件加载优先级

    1.基本语法k:(空格)v:表示一对键值对(一个空格必须有):以空格的缩进来控制层级关系:只要是左对齐的一列数据,都是同一个层级的属性和值也是大小写敏感: server: port: 8081 pat ...

  9. 使用纯注解与配置类开发springMVC项目,去掉xml配置

    最近拜读了杨开振老师的书,深入浅出springBoot2.x,挖掘了很多以前被忽略的知识, 开发一年多,工作中一直用传统springmvc的开发,基本都还是用的传统的xml配置开发, 看到书里有提到, ...

随机推荐

  1. 分区表的表进行update操作

    今天对一张创建了分区表的表进行update操作,正好需要修改的是创建分区的那一列,由于是要修改在分区表范围内的数据,所以无法修改. 然后搜了一下,需要修改row movement这个属性:alter ...

  2. E. Enemy is weak 解析(思維、離散化、BIT、線段樹)

    Codeforce 61 E. Enemy is weak 解析(思維.離散化.BIT.線段樹) 今天我們來看看CF61E 題目連結 題目 給一個數列\(a\),求有多少\((i,j,k)\),\(i ...

  3. viewpage轮播图

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com ...

  4. SpringBoot整合Logback日志框架配置全解析

    目录 本篇要点 一.Logback日志框架介绍 二.SpringBoot与Logback 1.默认日志格式 2.控制台输出 3.文件输出 4.日志级别 5.日志组 6.自定义log配置 三.logba ...

  5. NB-IoT技术适合在哪些场景应用

    LPWAN,Low Power Wide Area Network,低功耗广域网.名字里就有它的两个最重要的特点:低功耗.广覆盖.目前比较主流的有:NB-IoT.LoRa.Sigfox.eMTC.NB ...

  6. 云服务器部署Python项目(nginx+uwsgi+mysql+项目)

    python项目部署到云服务器 关注公众号"轻松学编程"了解更多. 一.硬件准备 云服务器,系统ubuntu_16_04 . 注意:要在安全组中开放Http的80端口. 二.软件准 ...

  7. PHP 教程:Composer 最佳实践

    概述 Composer 是 PHP 应用程序的依赖管理器,最初发布于大约 8 年前,2012 年 3 月. 在 php 中使用 Composer 可以提高代码的可重用性,并使你的项目能够轻松地集成来自 ...

  8. abp(net core)+easyui+efcore实现仓储管理系统——出库管理之五(五十四)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...

  9. 【QT】子类化QObject+moveToThread实现多线程

    往期链接: <QThread源码浅析> <子类化QThread实现多线程> 从往期<QThread源码浅析>可知,在Qt4.4之前,run 是纯虚函数,必须子类化Q ...

  10. ES6 小记

    1.let & const let:相当于var,不同的是没有变量提升,且只在声明的作用域内有效(新增了块级作用域). Const: 声明一个静态场量,一旦声明,常量的值就不能改变. for. ...