通过自定义注解 @NacosJsonConfig
自动加载 Nacos 中的 JSON 配置文件,并将其注入到指定的配置类字段中,你可以通过以下步骤实现:
1. 自定义注解 @NacosJsonConfig
首先,定义注解 @NacosJsonConfig
来标记需要从 Nacos 中加载 JSON 配置的字段。该注解的两个参数分别是 dataId
(配置文件标识)和 group
(配置组,默认为 DEFAULT_GROUP
)。
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NacosJsonConfig {
String dataId(); // Nacos 中的 dataId
String group() default "DEFAULT_GROUP";
}
2. 创建自定义处理逻辑
接下来,你需要创建一个自定义的处理器,负责在应用启动时从 Nacos 中读取指定的 JSON 配置文件,并将其解析后注入到配置类的字段中。你可以使用 BeanPostProcessor
或 InitializingBean
来实现此功能。
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.concurrent.Executor;
@Slf4j
@Component
public class NacosJsonConfigProcessor implements BeanPostProcessor {
private final NacosConfigManager nacosConfigManager;
public NacosJsonConfigProcessor(NacosConfigManager nacosConfigManager) {
this.nacosConfigManager = nacosConfigManager;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(NacosJsonConfig.class)) {
NacosJsonConfig annotation = field.getAnnotation(NacosJsonConfig.class);
String dataId = annotation.dataId();
String group = annotation.group();
try {
// 加载初始配置并注入
String config = nacosConfigManager.getConfigService().getConfig(dataId, group, 3000);
injectConfig(bean, field, config);
// 注册监听器,配置更新后重新注入
nacosConfigManager.getConfigService().addListener(dataId, group, new Listener() {
@Override
public Executor getExecutor() {
return null;
}
@Override
public void receiveConfigInfo(String configInfo) {
// 配置更新时动态注入
try {
log.info("重新载入配置文件:{}", dataId);
injectConfig(bean, field, configInfo);
} catch (Exception e) {
log.error("配置文件载入失败:{}", e.getMessage(), e);
}
}
});
} catch (Exception e) {
throw new BeansException("Failed to load config from Nacos", e) {
};
}
}
}
return bean;
}
/**
* 注入配置到字段
*
* @param bean 目标对象
* @param field 目标字段
* @param config 配置内容
*/
private void injectConfig(Object bean, Field field, String config) throws IllegalAccessException {
if (config != null) {
Object value = null;
if (JSONUtil.isTypeJSONArray(config)) {
value=JSONUtil.toBean(config, field.getGenericType(),true);
}else {
value=JSONUtil.toBean(config, field.getType());
}
field.setAccessible(true);
field.set(bean, value);
}
}
}
3. 配置 Nacos 服务
在 application.yml
中配置 Nacos 服务器地址:
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
4. 使用自定义注解的配置类
在配置类中,通过 @NacosJsonConfig
注解指定需要加载的 Nacos JSON 配置文件的 dataId
和 group
。
@Data
@Component
public class AppConfig{
@NacosJsonConfig(dataId = "test1.json")
private List<Test1> test1Config;
@NacosJsonConfig(dataId = "test2.json")
private List<Test2> test2Config;
}