nacos client加载自定义配置logback.xml的原理

为什么在我们spring boot项目中已经有了logback.xml文件的情况下,nacos client.jar包中自带的nacos-logback.xml(nacos-client 1.4.2版本验证)依然会生效?

问题的关键在于类com.alibaba.nacos.client.logging.logback.LogbackNacosLogging

public class LogbackNacosLogging extends AbstractNacosLogging {
    
    private static final String NACOS_LOGBACK_LOCATION = "classpath:nacos-logback.xml";
    
    @Override
    public void loadConfiguration() {
        String location = getLocation(NACOS_LOGBACK_LOCATION);
        if (StringUtils.isBlank(location)) {
            return;
        }
        
        try {
            // 这是加载自定义配置文件的关键
            // 第一步获取一个LoggerContext
            // 第二步使用LoggerContext加载location位置的配置文件
            LoggerContext loggerContext = (LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory();
            new ContextInitializer(loggerContext).configureByResource(ResourceUtils.getResourceUrl(location));
        } catch (Exception e) {
            throw new IllegalStateException("Could not initialize Logback Nacos logging from " + location, e);
        }
    }
    
}

 new ContextInitializer(loggerContext).configureByResource(ResourceUtils.getResourceUrl(location));

这行代码就是使用loggerContext加载location位置的配置文件

那么location指向哪里呢?

看这行代码

String location = getLocation(NACOS_LOGBACK_LOCATION);

private static final String NACOS_LOGGING_CONFIG_PROPERTY = "nacos.logging.config";
    
private static final String NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY = "nacos.logging.default.config.enabled";
    
protected String getLocation(String defaultLocation) {

    // 从system property中获取location的值
    String location = System.getProperty(NACOS_LOGGING_CONFIG_PROPERTY);
    // 如果没有从system property中获取到值,则直接使用默认配置
    if (StringUtils.isBlank(location)) {
        if (isDefaultConfigEnabled()) {
            return defaultLocation;
        }
        return null;
    }
    return location;
}

首先从system property中获取值,如果没有获取到再使用defaultLocation,而defaultLocation的值为classpath:nacos-logback.xml

这就解释了为什么nacos-logback.xml配置文件会被解析了。

这时候好奇的同学又会问了,那这段代码凭什么会执行?

直接执行代码是在nacos client中的类

com.alibaba.nacos.client.utils.LogUtils ,这段在LogUtils类的静态代码块中,只要LogUtils被jvm加载,这段代码就会执行

static {
    NacosLogging.getInstance().loadConfiguration();
    NAMING_LOGGER = getLogger("com.alibaba.nacos.client.naming");
}

com.alibaba.nacos.client.config.NacosConfigService使用了LogUtils,NacosConfigService被加载LogUtils就会被加载

private static final Logger LOGGER = LogUtils.logger(NacosConfigService.class);

com.alibaba.nacos.api.config.ConfigFactory使用了Class.forName加载了NacosConfigService

public static ConfigService createConfigService(Properties properties) throws 
    NacosException {
    try {
        // 使用Class.forName加载
        Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
        Constructor constructor = driverImplClass.getConstructor(Properties.class);
        ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
        return vendorImpl;
    } catch (Throwable e) {
        throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
    }
}

com.alibaba.nacos.api.NacosFactory调用了ConfigFactory.createConfigService()方法

public static ConfigService createConfigService(Properties properties) throws 
    NacosException {
        return ConfigFactory.createConfigService(properties);
}
com.alibaba.cloud.nacos.NacosConfigManager类调用了NacosFactory的createConfigService
public NacosConfigManager(NacosConfigProperties nacosConfigProperties) {
    this.nacosConfigProperties = nacosConfigProperties;
	// Compatible with older code in NacosConfigProperties,It will be deleted in the
	// future.
	createConfigService(nacosConfigProperties);
}

com.alibaba.cloud.nacos.NacosConfigBootstrapConfiguration中生成了NacosConfigManager

@Bean
@ConditionalOnMissingBean
public NacosConfigManager nacosConfigManager(
		NacosConfigProperties nacosConfigProperties) {
	return new NacosConfigManager(nacosConfigProperties);
}

而NacosConfigBootstrapConfiguration类则是,spring-cloud-starter-alibaba-nacos-config这个依赖通过spring的spi引入的

org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.NacosConfigBootstrapConfiguration

通过上面的一系列分析过程就能清楚了解nacos-logback.xml这个日志配置文件为什么会生效。其实这个加载过程跟My SQL驱动的加载过程有点像,区别是My SQL驱动是通过java的spi来加载,而前述的加载过程是通过spring的spi来完成的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值