0
点赞
收藏
分享

微信扫一扫

Java 通用配置(五)集成 Spring


​​Java 通用配置​​​​(一)设计​​​​(二)JVM和环境变量实现​​​​(三)用户配置实现​​​​(四)版本配置实现​​ (五)集成 Spring

本系列参考实现:

​​https://gitee.com/mybatis-mapper/config​​​​https://github.com/mybatis-mapper/config​​

作为一个 Java 通用配置管理,想让用户使用更简单,只需要依赖一个模块就行:

<dependency>
<groupId>io.mybatis</groupId>
<artifactId>mybatis-config</artifactId>
<version>1.0.0</version>
</dependency>

本系列写作过程中版本配置有变化,后续会发布 1.1.0 版本

如果用户运行在 Spring Boot 环境,就让 Spring Boot 相关配置自动生效,不用再增加和 spring 相关的通用配置依赖。

想要做到这一点就需要对可选的功能做好隔离,避免因为缺少类无法运行。

集成 Spring

想集成 Spring 肯定要先添加 Spring 依赖,因为是可选的支持,所以依赖也必须配置为可选:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.21</version>
<optional>true</optional>
</dependency>

设置 ​​<optional>true</optional>​​​ 之后,其他项目在依赖 ​​mybatis-config​​​ 时不会自动引入 spring 依赖,这就避免了依赖传递带来的污染,如果你在有 Spring Boot 的环境中添加了 ​​mybatis-config​​ 依赖,Spring 部分的功能就会自动生效。

针对 spring 单独创建了一个包,然后继承 ​​Config​​ 接口实现:

package io.mybatis.config.spring;

import io.mybatis.config.Config;

/**
* 支持 Spring 方式的属性配置,由于依赖 Spring EnvironmentAware 接口,当没有初始化时,过早执行时无法获取 Spring 配置
*/
public class SpringConfig implements Config {
/**
* 跳过当前方法获取
*/
private volatile boolean skip = false;

@Override
public int getOrder() {
return SPRING_ORDER;
}

@Override
public String getStr(String key) {
try {
return skip ? null : SpringEnvUtil.getStr(key);
} catch (NoClassDefFoundError e) {
//找不到类时,说明不是 Spring 运行环境
skip = true;
return null;
}
}
}

SpringConfig 是实现类,不是前两篇中的抽象类,是可以直接使用的,因此需要在第二篇中的 SPI 配置文件添加当前的配置。

在获取值时调用了 ​​SpringEnvUtil.getStr(key)​​​,这个类中用到了 Spring 的类,因此当没有集成 Spring 时,这里会抛出 ​​NoClassDefFoundError​​​ 错误,这里捕获异常后会将 ​​skip = true​​​,这样就避免了每次调用都抛出异常,如果跳过了,直接返回 null,然后交给下一个 Config 实现进行处理。继续看 ​​SpringEnvUtil​​ 工具类:

/**
* Spring 环境配置工具类,Spring boot 时自动注册,纯 Spring 时需要自己配置才能生效
*
* @author liuzh
*/
public class SpringEnvUtil implements EnvironmentAware {
private static Environment environment;
private static boolean enabled;

@Override
public void setEnvironment(Environment environment) {
SpringEnvUtil.environment = environment;
// 可以通过属性配置是否启用 Spring 支持,默认支持
SpringEnvUtil.enabled = environment.getProperty("io.mybatis.config.spring.enabled",
Boolean.class, true);
}

public static String getStr(String key) {
return (environment != null && enabled) ? SpringEnvUtil.environment.getProperty(key) : null;
}
}

这个类继承了 ​​EnvironmentAware​​​ 接口,并且通过 Spring 配置读取了 ​​io.mybatis.config.spring.enabled​​​,这里默认会启用,当不想使用 Spring 获取配置时,可以配置 ​​io.mybatis.config.spring.enabled=false​​。

这个类上没有加 Spring 的 ​​@Bean​​​ 相关的注解,因为使用者的包默认不会扫描这里,如果需要扫描才能生效,就会变的特别麻烦,如果使用的单纯的 Spring 环境(没有 Boot),就需要自己通过 ​​@Bean​​ 或者XML方式注册到自己系统,如果使用的 Spring Boot,就不需要任何处理,因为有下面的自动配置类:

@Configuration
public class SpringEnvAutoConfiguration {

@Bean
public SpringEnvUtil springEnvUtil() {
return new SpringEnvUtil();
}

}

为了让自动配置生效,在 ​​src/main/resources​​​ 下面的 ​​META-INF​​ 中存在 spring.factories 配置文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.mybatis.config.spring.SpringEnvAutoConfiguration

这样一来使用时就不需要任何配置了,引入 mybatis-config 后一切都自动生效。

假设在用户配置中存在 ​​mybatis.config.version=v1.0​​,在 Spring 的 yaml 配置中可以按下面方式直接写:

mybatis:
config:
version:

同时最早提到的命令行参数也自动支持了,例如:

java -jar xxx.jar --mybatis.config.version=v1.0

Spring 配置生效的情况下,Spring 如下的配置规则也就完全支持了:

Java 通用配置(五)集成 Spring_spring


此时我们提供的 ​​EnvConfig​​​, ​​SystemConfig​​ 就被 Spring 替代了,他们的优先级仍然是高于配置文件的,用的时候没有任何变化。

到这一篇时所有要实现的功能都已经完成了,除了第二篇实现写过简单测试外,后续的功能都还没有测试过,因此下一篇会针对用户配置、版本配置,Spring 配置进行测试,最后的最后还会发布因为写系列文章导致需求变化发布新版本的发布日志。


举报

相关推荐

0 条评论