Seata源码笔记(二)

基于incubartor-seata-2.x

配置相关的

ConfigurationFactory

静态代码块

initOriginConfiguration和maybeNeedOriginFileInstance逻辑较为简单,主要涉及FileConfiguration,load涉及Configuration代理

private static final String REGISTRY_CONF_DEFAULT = "registry";
private static final String ENV_SYSTEM_KEY = "SEATA_ENV";
public static final String ENV_PROPERTY_KEY = "seataEnv";

private static final String SYSTEM_PROPERTY_SEATA_CONFIG_NAME = "seata.config.name";

private static final String ENV_SEATA_CONFIG_NAME = "SEATA_CONFIG_NAME";

public static volatile Configuration CURRENT_FILE_INSTANCE;

public static volatile FileConfiguration ORIGIN_FILE_INSTANCE_REGISTRY;

public static volatile FileConfiguration ORIGIN_FILE_INSTANCE = null;

static {
	// 负责初始化ORIGIN_FILE_INSTANCE_REGISTRY(FileConfiguration),通过读取registry.conf(<configName>-<envName>.conf)
    initOriginConfiguration();
    // 初始化CURRENT_FILE_INSTANCE(判断是否有extConfiguration,没有就用ORIGIN_FILE_INSTANCE_REGISTRY,本来FileConfiguration就是Configuration的实现)
    // ext默认有个SpringBootConfigurationProvider实现,返回一个代理对象(seata-spring-autoconfigure-core里)
    load();
    // 如果CURRENT_FILE_INSTANCE是.conf的(也就是load用的还是registry.conf)
    // 那原配置文件ORIGIN_FILE_INSTANCE就用的registry.conf里的config.file.name(test中给的file.conf)
    maybeNeedOriginFileInstance();
}

FileConfiguration

继承自AbstractConfiguration,主要有两类方法和对应的两个内部类:

config相关方法: 对应内部类ConfigOperateRunnable,其中getLatestConfig是核心,AbstractConfiguration所有get方法都是调用的getLatestConfig,该方法优先找系统配置(System.getProperty),再异步获取本地文件配置(get方法会被下面的load()代理,导致优先走代理逻辑)。putConfig、removeConfig等方法目前还没实现,在ConfigOperateRunnable里都是todo。

listener相关方法:对应内部类FileListener,主要设置dataId对应的监听器,在file.listener.enabled为true时,每1000ms一次获取dataId的最新值。

SpringBootConfigurationProvider

对应load()方法。融入spring获取value的方式。主要是通过SPI去找ExtConfigurationProvider的实现然后调用provide方法,目前唯一提供的实现SpringBootConfigurationProvider,它是通过动态代理创建一个Configuration的代理对象,来拦截并设置get方法获取的值

public class SpringBootConfigurationProvider implements ExtConfigurationProvider {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpringBootConfigurationProvider.class);

    private static final String INTERCEPT_METHOD_PREFIX = "get";

    private static final Map<String, Object> PROPERTY_BEAN_INSTANCE_MAP = new ConcurrentHashMap<>(64);

    @Override
    public Configuration provide(Configuration originalConfiguration) {
        return (Configuration)Enhancer.create(originalConfiguration.getClass(),
            (MethodInterceptor)(proxy, method, args, methodProxy) -> {
                if (method.getName().startsWith(INTERCEPT_METHOD_PREFIX) && args.length > 0) {
                    Object result;
                    String rawDataId = (String)args[0];
                    Class<?> dataType = ReflectionUtil.getWrappedClass(method.getReturnType());

                    // 1. Get config value from the system property
                    result = originalConfiguration.getConfigFromSys(rawDataId);

                    if (result == null) {
                        String dataId = convertDataId(rawDataId);

                        // 2. Get config value from the springboot environment
                        result = getConfigFromEnvironment(dataId, dataType);
                        if (result != null) {
                            return result;
                        }

                        // 3. Get config defaultValue from the arguments
                        if (args.length > 1) {
                            result = args[1];

                            if (result != null) {
                                // See Configuration#getConfig(String dataId, long timeoutMills)
                                if (dataType.isAssignableFrom(result.getClass())) {
                                    return result;
                                } else {
                                    result = null;
                                }
                            }
                        }

                        // 4. Get config defaultValue from the property object
                        try {
                            result = getDefaultValueFromPropertyObject(dataId);
                        } catch (Throwable t) {
                            LOGGER.error("Get config '{}' default value from the property object failed:", dataId, t);
                        }
                    }

                    if (result != null) {
                        if (dataType.isAssignableFrom(result.getClass())) {
                            return result;
                        }

                        // Convert type
                        return this.convertType(result, dataType);
                    }
                }

                return method.invoke(originalConfiguration, args);
            });
    }
    ...
}
Configuration的get方法拦截后,value取值优先级

result,也就是get方法的结果读取优先级:

1、环境变量(步骤1里getenv和getProperty)
2、ApplicationContext(步骤2里的ObjectHolder,很贴心的做了各种变换去找,下面会去看ObjectHolder怎么来的)
3、Configuration.getConfig(String dataId, String defaultValue…)(步骤3取默认值)
4、 从PROPERTY_BEAN_MAP获取(步骤4,下面会去看PROPERTY_BEAN_MAP怎么来的)

ObjectHolder

seata-spring-autoconfigure-core的spring.factories配了个自动配置项SeataCoreAutoConfiguration
在这里插入图片描述在这里插入图片描述在这里插入图片描述

PROPERTY_BEAN_MAP

同上,seata-spring-autoconfigure-core的spring.factories配了个自动配置项SeataCoreEnvironmentPostProcessor,并且client和server包里也配置了SeataClientEnvironmentPostProcessor和SeataServerEnvironmentPostProcessor
在这里插入图片描述

getInstance

buildConfiguration

reload

工作去了,晚点更

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_tt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值