自己实现一个简单的Nacos配置启动类

该文章介绍了如何模拟实现Nacos配置中心的核心功能,包括配置的加载和动态更新。通过创建一个starter,引入相关依赖,并配置spring.factories,实现在Spring Boot应用启动时加载Nacos配置。代码中定义了BootstrapConfiguration和ConfigAutoConfiguration,用于加载和监听配置变化,当配置发生变更时,发布RefreshEvent事件来刷新配置。示例提供了配置文件内容和加载过程,以及NacosConfigService的关键操作。

此文章只是简单的实现了对应的nacos配置中心的核心功能,只是模拟了nacos配置的核心功能,包括一些配置的加载,动态更新。

直接上代码。

首先我们要写一个starter,需要引入对应的stater依赖。并且配置对应的spring.factories

pom依赖如下所示:

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.1.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

spring.factories 如下:加载了两个类:

org.springframework.cloud.bootstrap.BootstrapConfiguration=\
edu.mbb.cloud.nacos.ConfigBootstrapConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
edu.mbb.cloud.nacos.ConfigAutoConfiguration

BootstrapConfiguration 是指加载bootstrap.yaml或者properties的时候加载的类。此时对应的配置文件已经加载进去对应的容器中,对应的我们已经取到了对应的bootstarp的配置信息,这也就是为啥我们的配置的nacos 信息要在对应的bootstrap.yaml中。
@Configuration
@ConditionalOnProperty(name = "spring.mbb.enable",matchIfMissing = true)
public class ConfigBootstrapConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public MbbConfigProPerties mbbConfigProPerties(){
        return  new MbbConfigProPerties();
    }


    @Bean
    public MbbPropertySourceLocator mbbPropertySourceLocator(
            MbbConfigProPerties mbbConfigProPerties) {
        return new MbbPropertySourceLocator(mbbConfigProPerties);
    }

主要是加载了下面的MbbPropertySourceLocator 这个bean 注入了nacos 的配置信息。

而MbbPropertySourceLocator 实现了PropertySourceLocator 接口,此接口是springcloud为了加载对应的配置文件信息到对应的容器中去。我们集成此接口也会把我们自己的对应的配置信息加载到对应的容器中去。

public PropertySource<?> locate(Environment environment) 重写此方法

CompositePropertySource 返回值为这个 

所以我们只需要把对应的配置信息加载进到这个类中即可。

我们有了nacos的配置信息,此时就把对应的nacos配置信息用来连接nacos。

从nacos上找到了对应的信息后,加载进去到CompositePropertySource这个类中。

nacos 中会加载两个配置文件一个是你激活的文件一个是对应的项目名称文件。至于为啥激活两个,问了nacos社区的人。。。。。他们没回复,我也不知道为啥。。。

server:
  port: 4466

spring:
  profiles:
    active: dev
  application:
    name: nacos-config-client
  mbb:
    server-addr: localhost:8848 #Nacos作为配置中心地址
    file-extension: yaml #指定yaml格式配置
    group: TEST_GROUP
    namespace: b8b51e18-7395-4124-8840-fe39fde231b1
 

假如我的配置信息长成这个样子。。。

他会加载两个配置文件>>>>一个是nacos-config-client.yaml 和 nacos-config-client-dev.yaml 

还有一个加载的类,ConfigAutoConfiguration 加载了 MyContextRefresher 

实现了两个接口 ApplicationListener<ApplicationReadyEvent>, ApplicationContextAware

ApplicationListener这个监听就是为了监听当spring容器加载完成的时候 才开始进行对应的事件监听操作。 下面的接口为了注入ApplicationContext 对象。

此方法主要为了给对应的文件添加监听。

configService.addListener(dataId, group, listener);
并在文件内容有变动的时候进行对应的发布对应的RefreshEvent事件,刷新对应的refreshscope对象
applicationContext.publishEvent(
        new RefreshEvent(this, null, "Refresh Nacos config"));

NacosConfigService 是nacos 操作核心类。原生的nacos有对应的CRUD的监听操作。我这里只模拟了对应的add方法

具体还是看代码我把代码放上去,并且给出一个demo用来使用。使用的 

这个模块 

https://gitee.com/mibaowei/my-nacos.git 

<think>嗯,用户问的是在Spring Boot中,如果有多个Service接口的实现,如何通过Nacos配置来决定使用哪一个。首先,我得回忆一下Spring Boot中处理多个实现的方式,通常是用@Qualifier或者@Conditional之类的注解。然后结合Nacos的动态配置,可能需要用到@NacosValue或者@NacosConfigurationProperties来获取配置的值。 用户可能是在微服务架构中,希望通过外部配置来灵活切换不同的服务实现,而不需要重新部署代码。比如,不同的环境使用不同的实现,或者进行A/B测试。这时候,Nacos作为配置中心,可以动态管理这些配置。 首先,我需要确认如何将Nacos配置注入到Spring中。通常的做法是使用@NacosValue注解,或者通过@ConfigurationProperties绑定配置类。然后,在Service的实现类上,使用条件注解,比如@ConditionalOnProperty,根据配置的值来决定哪个实现被加载。 可能的步骤是: 1. 在Nacos配置中心创建一个配置文件,比如定义一个属性service.impl.version=1。 2. 在Spring Boot项目中,引入Nacos的依赖和配置,确保能够读取到Nacos配置。 3. 编写多个Service的实现类,每个实现类用不同的条件注解,根据配置的值来决定哪个被激活。 4. 在业务层注入Service的时候,根据配置选择正确的实现。 不过,可能还需要考虑@Primary注解来指定默认的实现,或者在配置不存在时的回退策略。另外,动态刷新的问题,如果配置变更后,是否需要重启应用,还是可以热加载。可能需要结合@RefreshScope来实现配置的动态更新。 用户可能有多个实现类,比如ServiceImplV1和ServiceImplV2,他们实现了同一个Service接口。这时候,如何根据配置来注入不同的实例。可能需要使用@ConditionalOnProperty,根据配置的属性值来决定哪个类被实例化。 例如: 在配置文件中设置service.impl=implV1,然后在ServiceImplV1类上添加@ConditionalOnProperty(name = "service.impl", havingValue = "implV1"),同理处理V2版本。这样,当配置中的值改变时,相应的实现类会被激活。 另外,如果用户不想使用条件注解,还可以通过@Bean方法在配置类中根据配置值返回不同的实例。比如在@Configuration类中,使用@NacosValue获取配置,然后返回对应的实现类。 需要注意的是,如果多个实现类都没有被条件注解排除,Spring可能会因为找到多个Bean而报错,所以必须确保只有一个实现类被激活,或者使用@Primary来指定默认的Bean。 还有,Nacos配置需要正确加载,确保应用启动时能够连接到Nacos服务器,并且配置的Data ID、Group等参数正确。 用户可能遇到的问题包括:配置未正确加载,导致没有符合条件的Bean被创建;多个Bean冲突;动态配置更新后无法生效等。需要检查Nacos配置的格式是否正确,是否在bootstrap.yml中正确配置Nacos的信息,以及是否处理了配置刷新的逻辑。 总结一下,步骤大致是: 1. 添加Nacos依赖和配置。 2. 定义多个Service实现,并使用条件注解或配置类根据Nacos配置选择实现。 3. 注入Service时确保正确的Bean被使用。 4. 处理配置动态刷新(如果需要)。 可能需要给出具体的代码示例,比如如何在Nacos中设置配置,如何在实现类上添加条件注解,以及如何在配置类中动态创建Bean。同时提醒用户注意Bean的冲突问题,以及配置的正确加载方式。</think>在 Spring Boot 中,当同一个 Service 接口有多个实现类时,可以通过 **Nacos 配置中心**结合 **Spring 的条件注解**(如 `@ConditionalOnProperty`)或 **自定义逻辑** 动态选择具体实现。以下是具体实现步骤: --- ### 1. 添加 Nacos 依赖 在 `pom.xml` 中确保已引入 Nacos 配置依赖: ```xml <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> ``` --- ### 2. 在 Nacos 中定义配置Nacos 控制台创建配置文件(如 `service-config.yaml`),定义选择实现类的标识: ```yaml # Data ID: service-config.yaml # Group: DEFAULT_GROUP service: impl: strategy: "v1" # 可配置为 v1/v2/custom ``` --- ### 3. 实现多个 Service 接口 定义接口及多个实现类: ```java public interface DemoService { String execute(); } // 实现类1:v1版本 @Component("v1") @ConditionalOnProperty(name = "service.impl.strategy", havingValue = "v1") public class DemoServiceImplV1 implements DemoService { @Override public String execute() { return "V1 实现"; } } // 实现类2:v2版本 @Component("v2") @ConditionalOnProperty(name = "service.impl.strategy", havingValue = "v2") public class DemoServiceImplV2 implements DemoService { @Override public String execute() { return "V2 实现"; } } ``` --- ### 4. 动态注入 Service 实现 通过 `@NacosValue` 读取配置,结合 `@Autowired` 和 `@Qualifier` 动态注入 Bean: ```java @RestController public class DemoController { @NacosValue(value = "${service.impl.strategy}", autoRefreshed = true) private String strategy; @Autowired private ApplicationContext applicationContext; @GetMapping("/execute") public String execute() { DemoService demoService = (DemoService) applicationContext.getBean(strategy); return demoService.execute(); } } ``` --- ### 5. 配置 Nacos 连接信息 在 `bootstrap.yml` 中配置 Nacos 地址及监听文件: ```yaml spring: application: name: your-service-name cloud: nacos: config: server-addr: ${NACOS_HOST:localhost}:8848 file-extension: yaml namespace: your-namespace-id # 可选命名空间 group: DEFAULT_GROUP # 配置分组 ``` --- ### 6. 动态切换实现类 - **无需重启服务**:直接修改 Nacos 中 `service.impl.strategy` 的值(如改为 `v2`),Nacos 会推送新配置到应用。 - 通过 `@NacosValue` 的 `autoRefreshed = true` 属性实现配置热更新。 --- ### 关键点总结 1. **条件注解**:通过 `@ConditionalOnProperty` 控制 Bean 的加载条件。 2. **动态注入**:根据配置值从 Spring 容器中获取对应 Bean。 3. **热更新**:Nacos 配置变更后自动生效。 --- ### 扩展场景 如果需更复杂的选择逻辑(如根据环境、参数动态路由),可结合 `@Bean` 和自定义选择器: ```java @Configuration public class ServiceConfig { @Bean public DemoService demoService(@Value("${service.impl.strategy}") String strategy) { return switch (strategy) { case "v1" -> new DemoServiceImplV1(); case "v2" -> new DemoServiceImplV2(); default -> throw new IllegalArgumentException("未知策略"); }; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值