欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

深入 Spring Boot:编写兼容 Spring Boot1 和 Spring Boot2 的 Starter

点击: 次  来源:宝鼎软件 时间:2018-07-30

原文出处: hengyunabc

前言

Spring Boot 2正式发布已经有段时间,应用升级之前,starter先要升级,那么如何支持Spring Boot 2?

starter同时兼容spring-boot-1和spring-boot-2">为什么选择starter同时兼容spring boot 1和spring boot 2

从用户角度来看

如果不在一个starter里兼容,比如用版本号来区分,spring boot 1的用户使用1.*,spring boot 2用户使用2.*,这样用户升级会有很大困扰。

另外,我们的starter是以日期为版本号的,如果再分化,则就会出现2018-06-stable-boot12018-06-stable-boot2,这样子很丑陋。

从开发者角度来看

要同时维护两个分支,劳务派遣管理系统,修改代码时要合到两个分支上,发版本时要同时两个。如果有统一的bom文件,也需要维护两份。工作量翻倍,昆山软件开发,而且很容易出错。

因此,我们决定在同一个代码分支里,同时支持spring boot 1/2。减少开发维护成本,减少用户使用困扰。

编写兼容的starter的难点

spring boot starter的代码入口都是在各种@Configuration类里,这为我们编写兼容starter提供了条件。

但还是有一些难点:

  • 某些类不兼容,比如在spring boot 2里删除掉了
  • 代码模块,maven依赖怎样组织
  • 怎样保证starter在spring boot 1/2里都能正常工作
  • 通过ASM分析现有的starter里不兼容的类

  • https://github.com/hengyunabc/springboot-classchecker
  • springboot-classchecker可以从jar包里扫描出哪些类在spring boot 2里不存在的。

    工作原理:springboot-classchecker自身在pom.xml里依赖的是spring boot 2,扫描jar包里通过ASM分析到所有的String,提取出类名之后,再尝试在ClassLoader里加载,如果加载不到,则说明这个类在spring boot 2里不存在。

    例如扫描demo-springboot1-starter.jar :

    mvn clean package
    java -jar target/classchecker-0.0.1-SNAPSHOT.jar demo-springboot1-starter.jar

    结果是:

    path: demo-springboot1-starter.jar
    org.springframework.boot.actuate.autoconfigure.ConditionalOnEnabledHealthIndicator
    org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration
    org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration

    那么这些类在spring boot 2在哪里了?

    实际上是改了package:

    org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator
    org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration
    org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration

    通过扫描20多个starter jar包,昆山软件开发,发现不兼容的类有:

  • org.springframework.boot.env.PropertySourcesLoader
  • org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder
  • org.springframework.boot.bind.RelaxedDataBinder
  • Endpoint/HealthIndicator 相关的类
  • 可以总结:

  • spring boot核心的类,autoconfigure相关的没有改动
  • 大部分修改的是Endpoint/HealthIndicator 相关的类
  • spring-boot-utils兼容工具类

  • https://github.com/hengyunabc/spring-boot-utils
  • spring-boot-utils提供兼容工具类,同时支持spring boot 1/2。

    BinderUtils

    在spring boot 1里,注入环境变量有时需要用到RelaxedDataBinder

    MyProperties myProperties = new MyProperties();
    MutablePropertySources propertySources = environment.getPropertySources();
    new RelaxedDataBinder(myProperties, "spring.my").bind(new PropertySourcesPropertyValues(propertySources));

    在spring boot 2里,RelaxedDataBinder删除掉了,新的写法是用Binder

    Binder binder = Binder.get(environment);
    MyProperties myProperties = binder.bind("spring.my", MyProperties.class).get();

    通过BinderUtils,则可以同时支持spring boot1/2:

    MyProperties myProperties = BinderUtils.bind(environment, "spring.my", MyProperties.class);

    @ConditionalOnSpringBoot1/@ConditionalOnSpringBoot2

    spring boot starter的功能大部分都是通过@Configuration组装起来的。spring boot 1的Configuration类,不能在spring boot 2里启用。则可以通过@ConditionalOnSpringBoot1@ConditionalOnSpringBoot2这两个注解来分别支持。