前言

这里是继上文中,关于数据源配置了下划线之后读取不到的问题的探究。再上篇文章中我在文章里强调了这个问题,网上说的模棱两可。官方文档也未作出详细说明,所以自己花了点时间,进行调试略有心得,在这里分享!

前文

《Sharding-JDBC简单使用》
《Sharding-JDBC主子表(绑定表)关联》
《Sharding-JDBC读写分离配置》

故障重现

我在配置文件里,给数据源名称设置了下划线,然后报错
在这里插入图片描述
在这里插入图片描述
根据代码调试原则,哪里能点点哪里。

调试之旅

我们看这里,是放置数据源的地方org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration.setEnvironment
在这里插入图片描述
Map<String, Object> dataSourceProps = (Map)PropertyUtil.handle(environment, prefix + dataSourceName.trim(), Map.class);

这行代码往下就报错,说明问题就是从这里抛出来的进去!!!
调试代码就是要一点点重来一点点进(谁让我菜,我只能这样,你要是有走读代码的能力,自然更好!)

在这里插入图片描述
springboot1.x走v1,springboot2.x走v2,这里并不是重点
在这里插入图片描述

    @SneakyThrows
    private static Object v2(final Environment environment, final String prefix, final Class<?> targetClass) {
        Class<?> binderClass = Class.forName("org.springframework.boot.context.properties.bind.Binder");
        Method getMethod = binderClass.getDeclaredMethod("get", Environment.class);
        Method bindMethod = binderClass.getDeclaredMethod("bind", String.class, Class.class);
        Object binderObject = getMethod.invoke(null, environment);
        String prefixParam = prefix.endsWith(".") ? prefix.substring(0, prefix.length() - 1) : prefix;
        //这里是关键,你看他究竟反射调用哪个方法!
        Object bindResultObject = bindMethod.invoke(binderObject, prefixParam, targetClass);
        Method resultGetMethod = bindResultObject.getClass().getDeclaredMethod("get");
        return resultGetMethod.invoke(bindResultObject);
    }

他这里反射调用了binder

binder里的bind方法有很多重载,不过都不重要,因为他根本进行不下去,说明在进去的那个方法就报错所以说细看

this.bind((ConfigurationPropertyName)ConfigurationPropertyName.of(name), target, (BindHandler)null);

进入ConfigurationPropertyName.of(name)
在这里插入图片描述
一路进入到这里
在这里插入图片描述
直接看这里

Elements elements = (new ElementsParser(name, ‘.’, parserCapacity)).parse();

for(int i = 0; i < length; ++i) {
                char ch = this.source.charAt(i);
                if (ch == '[') {
                    if (openBracketCount == 0) {
                        this.add(start, i, type, valueProcessor);
                        start = i + 1;
                        type = ConfigurationPropertyName.ElementType.NUMERICALLY_INDEXED;
                    }

                    ++openBracketCount;
                } else if (ch == ']') {
                    --openBracketCount;
                    if (openBracketCount == 0) {
                        this.add(start, i, type, valueProcessor);
                        start = i + 1;
                        type = ConfigurationPropertyName.ElementType.EMPTY;
                    }
                } else if (!type.isIndexed() && ch == this.separator) {
                    this.add(start, i, type, valueProcessor);
                    start = i + 1;
                    type = ConfigurationPropertyName.ElementType.EMPTY;
                } else {
                    type = this.updateType(type, ch, i - start);
                }
            }

直接把遍历的下标条件设置成35,方便自己一直调试
https://blog.csdn.net/weixin_43953546/article/details/102807792 左击打断点,右击输入条件
在这里插入图片描述

这里我们能看到他是在遍历spring.shardingsphere.datasource.ds0_master这个字符串,到这里我们大概能猜到了,可能是这个_ , 这里属于非法字符串(猜对了)

在这里插入图片描述
断点进入到isValidChar这个方法!
在这里插入图片描述
其实到这里,看名字我们都能猜到并证实自己猜想了
在这里插入图片描述

必须是a-z 或则 0-9或者-,其余都是非法字符串!!

反证

取消下划线,使用大写M,执行,果然报错!
在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐