栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

仿nacos配置中心

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

仿nacos配置中心

使用nacos的时候,我们可以把某些配置写在nacos上面,以便于我们修改,那么如何能简单的实现这一功能呢?先看图

看到该图我们发现他是一个map结构,也就是说我们可以在spring初始化完毕之后可以往该map中添加k-v,我们可以通过environment.getProperty("server.port");去获取,这当然没毛病,但是我们使用@Value注解去获取值的时候就不行了,因为spring的bean默认是单例的,这是因为你虽然把值put进去了,这个时候bean已经生成了,bean里面的属性值肯定还是为null。如何解决呢?初始化完所有bean后销毁当前bean,重新生成该bean。

下面上代码

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {

    private BeanDefinitionRegistry beanDefinitionRegistry;

    
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        this.beanDefinitionRegistry = beanDefinitionRegistry;
    }

    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        configurableListableBeanFactory.registerScope("myRefreshScope", new MyRefreshScope());
    }

    public BeanDefinitionRegistry getBeanDefinitionRegistry() {
        return beanDefinitionRegistry;
    }
}

我们定义一个类去实现Scope,由于使用不到其中的方法,所以暂时不用去实现方法

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.stereotype.Component;

@Component
public class MyRefreshScope implements Scope {


    @Override
    public Object get(String s, ObjectFactory objectFactory) {
        return null;
    }

    @Override
    public Object remove(String s) {
        return null;
    }

    @Override
    public void registerDestructionCallback(String s, Runnable runnable) {

    }

    @Override
    public Object resolveContextualObject(String s) {
        return null;
    }

    @Override
    public String getConversationId() {
        return null;
    }
}

核心代码来了

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.stereotype.Component;


@Component
public class StartReadConfiguration  implements EnvironmentAware , ApplicationListener {

    private StandardEnvironment environment;

    private BeanDefinitionRegistry beanDefinitionRegistry;

    @Autowired
    private MyBeanDefinitionRegistry myBeanDefinitionRegistry;

    @Autowired
    ConfigurableApplicationContext applicationContext;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = (StandardEnvironment) environment;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        beanDefinitionRegistry = myBeanDefinitionRegistry.getBeanDefinitionRegistry();
        init();
    }

    public void init (){
        MutablePropertySources propertySources = environment.getPropertySources();
        propertySources.forEach(propertySource -> {
            if (propertySource instanceof OriginTrackedMapPropertySource) {
                OriginTrackedMapPropertySource originTrackedMapPropertySource
                        = (OriginTrackedMapPropertySource) propertySource;
                originTrackedMapPropertySource.getSource().put("test.name","ljw1");
                // 刷新配置
                String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
                for (String beanDefinitionName : beanDefinitionNames) {
                    BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanDefinitionName);
                    if ("myRefreshScope".equals(beanDefinition.getScope())) {
                        //销毁当前bean
                        applicationContext.getBeanFactory().destroyBean(beanDefinitionName);
                        //重新获取生成bean,这个 时候属性已经注入进去了
                        Object bean = applicationContext.getBean(beanDefinitionName);
                    }
                }
            }
        });
    }
}

测试代码

@RestController
@Scope("myRefreshScope")
public class NacosController {


    @Value("${test.name}")
    private String name;

    @Autowired
    Environment environment;

    @GetMapping("/")
    public  String getString(){
        //String property = environment.getProperty("server.port");
        return "HelloWorld"+name;
    }
}

效果如下

那这个时候就会有人说了,你这样不还是把配置在代码中写死了吗。
这只是 一个核心思想,我们可以把数据写在数据库中,通过读取数据库来把信息注入进去
优化点:1、数据库存配置信息 2、通过定时任务及时刷新配置信息 3、增加一个MD5值取进行比较,不用每次都刷新所有。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/682515.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号