• nacos-spring-project 的注解配置


    spring 项目可以通过注解方式使用 nacos-client

    使用示例

    @Configuration
    @EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))
    @NacosPropertySource(dataId = "example", autoRefreshed = true)
    public class NacosConfiguration {
    
    }

    加 @Configuration 注解,spring 容器会创建一个对象放到容器中

    通过 @EnableNacosConfig 注解,import NacosConfigBeanDefinitionRegistrar,注册 bean

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(NacosConfigBeanDefinitionRegistrar.class)
    public @interface EnableNacosConfig {
        NacosProperties globalProperties() default
                @NacosProperties(
                        endpoint = ENDPOINT_PLACEHOLDER,
                        namespace = NAMESPACE_PLACEHOLDER,
                        accessKey = ACCESS_KEY_PLACEHOLDER,
                        secretKey = SECRET_KEY_PLACEHOLDER,
                        serverAddr = SERVER_ADDR_PLACEHOLDER,
                        contextPath = CONTEXT_PATH_PLACEHOLDER,
                        clusterName = CLUSTER_NAME_PLACEHOLDER,
                        encode = ENCODE_PLACEHOLDER,
                        configLongPollTimeout = CONFIG_LONG_POLL_TIMEOUT_PLACEHOLDER,
                        configRetryTime = CONFIG_RETRY_TIME_PLACEHOLDER,
                        maxRetry = MAX_RETRY_PLACEHOLDER
                );
    }

    重点在 NacosConfigBeanDefinitionRegistrar,注册一些简单 bean 和 post processor 的 bean,例如 NacosPropertySourcePostProcessor,

    NacosPropertySourcePostProcessor 它扫描容器中的 bean,如果有 @NacosPropertySource 注解,则解析出注解中的属性,并从 nacos server 拉取配置,并保存到 environment 中

    // com.alibaba.nacos.spring.context.annotation.config.NacosConfigBeanDefinitionRegistrar#registerBeanDefinitions
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes attributes = fromMap(metadata.getAnnotationAttributes(EnableNacosConfig.class.getName()));
        // Register Global Nacos Properties Bean
        registerGlobalNacosProperties(attributes, registry, environment, CONFIG_GLOBAL_NACOS_PROPERTIES_BEAN_NAME);
        // Register Nacos Common Beans
        registerNacosCommonBeans(registry);
        // Register Nacos Config Beans
        registerNacosConfigBeans(registry, environment);
        // Invoke NacosPropertySourcePostProcessor immediately
        // in order to enhance the precedence of @NacosPropertySource process
        invokeNacosPropertySourcePostProcessor(beanFactory);
    }
    
    直接调用 NacosPropertySourcePostProcessor
    // com.alibaba.nacos.spring.util.NacosBeanUtils#invokeNacosPropertySourcePostProcessor
    public static void invokeNacosPropertySourcePostProcessor(BeanFactory beanFactory) {
        NacosPropertySourcePostProcessor postProcessor =
                beanFactory.getBean(NacosPropertySourcePostProcessor.BEAN_NAME, NacosPropertySourcePostProcessor.class);
        postProcessor.postProcessBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    }
    
    // com.alibaba.nacos.spring.core.env.NacosPropertySourcePostProcessor#postProcessBeanFactory
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String[] abstractNacosPropertySourceBuilderBeanNames = BeanUtils.getBeanNames(beanFactory,
            AbstractNacosPropertySourceBuilder.class);
    
        this.nacosPropertySourceBuilders = new ArrayList<AbstractNacosPropertySourceBuilder>(
            abstractNacosPropertySourceBuilderBeanNames.length);
    
        for (String beanName : abstractNacosPropertySourceBuilderBeanNames) {
            // 设置 NacosPropertySource 的 builder
            this.nacosPropertySourceBuilders.add(
                beanFactory.getBean(beanName, AbstractNacosPropertySourceBuilder.class));
        }
    
        // 设置 ConfigService 的 builder
        this.configServiceBeanBuilder = getConfigServiceBeanBuilder(beanFactory);
    
        String[] beanNames = beanFactory.getBeanDefinitionNames();
    
        for (String beanName : beanNames) {
            processPropertySource(beanName, beanFactory);
        }
    
    }
    
    // com.alibaba.nacos.spring.core.env.NacosPropertySourcePostProcessor#processPropertySource
    private void processPropertySource(String beanName, ConfigurableListableBeanFactory beanFactory) {
    
        if (processedBeanNames.contains(beanName)) {
            return;
        }
    
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
    
        // 拉取配置
        // Build multiple instance if possible
        List<NacosPropertySource> nacosPropertySources = buildNacosPropertySources(beanName, beanDefinition);
    
        // Add Orderly
        for (NacosPropertySource nacosPropertySource : nacosPropertySources) {
            // 加入到 environment 中
            addNacosPropertySource(nacosPropertySource);
            addListenerIfAutoRefreshed(nacosPropertySource);
        }
    
        processedBeanNames.add(beanName);
    }
    
    对 bean 上的注解进行筛选
    // com.alibaba.nacos.spring.core.env.NacosPropertySourcePostProcessor#buildNacosPropertySources
    private List<NacosPropertySource> buildNacosPropertySources(String beanName, BeanDefinition beanDefinition) {
        for (AbstractNacosPropertySourceBuilder builder : nacosPropertySourceBuilders) {
            if (builder.supports(beanDefinition)) {
                return builder.build(beanName, beanDefinition);
            }
        }
        return Collections.emptyList();
    }
    
    真正拉取配置
    // com.alibaba.nacos.spring.core.env.AbstractNacosPropertySourceBuilder#build
    public List<NacosPropertySource> build(String beanName, T beanDefinition) {
    
        Map<String, Object>[] attributesArray = resolveRuntimeAttributesArray(beanDefinition, globalNacosProperties);
    
        int size = attributesArray == null ? 0 : attributesArray.length;
    
        if (size == 0) {
            return Collections.emptyList();
        }
    
        List<NacosPropertySource> nacosPropertySources = new ArrayList<NacosPropertySource>(size);
    
        for (int i = 0; i < size; i++) {
            Map<String, Object> attributes = attributesArray[i];
            if (!CollectionUtils.isEmpty(attributes)) {
    
                NacosPropertySource nacosPropertySource = doBuild(beanName, beanDefinition, attributesArray[i]);
    
                NacosConfigMetadataEvent metadataEvent = createMetaEvent(nacosPropertySource, beanDefinition);
    
                initMetadataEvent(nacosPropertySource, beanDefinition, metadataEvent);
    
                publishMetadataEvent(metadataEvent);
    
                nacosPropertySources.add(nacosPropertySource);
    
            }
        }
    
        return nacosPropertySources;
    }
    
    解析 NacosPropertySources 和 NacosPropertySource 注解上的属性
    // com.alibaba.nacos.spring.core.env.AnnotationNacosPropertySourceBuilder#getAnnotationAttributesList
    private List<Map<String, Object>> getAnnotationAttributesList(
            AnnotationMetadata metadata, String annotationType) {
    
        List<Map<String, Object>> annotationAttributesList = new LinkedList<Map<String, Object>>();
    
        if (NacosPropertySources.class.getName().equals(annotationType)) {
            Map<String, Object> annotationAttributes = metadata
                    .getAnnotationAttributes(annotationType);
            if (annotationAttributes != null) {
                annotationAttributesList.addAll(Arrays.asList(
                        (Map<String, Object>[]) annotationAttributes.get("value")));
            }
        }
        else if (com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource.class
                .getName().equals(annotationType)) {
            annotationAttributesList
                    .add(metadata.getAnnotationAttributes(annotationType));
        }
        return annotationAttributesList;
    }
    
    // com.alibaba.nacos.spring.core.env.AbstractNacosPropertySourceBuilder#doBuild
    protected NacosPropertySource doBuild(String beanName, T beanDefinition, Map<String, Object> runtimeAttributes) {
    
        // Get annotation metadata
        String name = (String) runtimeAttributes.get(NAME_ATTRIBUTE_NAME);
        String dataId = (String) runtimeAttributes.get(DATA_ID_ATTRIBUTE_NAME);
        String groupId = (String) runtimeAttributes.get(GROUP_ID_ATTRIBUTE_NAME);
        Map<String, Object> nacosPropertiesAttributes = (Map<String, Object>) runtimeAttributes.get(PROPERTIES_ATTRIBUTE_NAME);
    
        Properties nacosProperties = resolveProperties(nacosPropertiesAttributes, environment, globalNacosProperties);
    
        String nacosConfig = nacosConfigLoader.load(dataId, groupId, nacosProperties);
    
        if (!StringUtils.hasText(nacosConfig)) {
            if (logger.isWarnEnabled()) {
                logger.warn(format("There is no content for NacosPropertySource from dataId[%s] , groupId[%s] , properties[%s].",
                        dataId,
                        groupId,
                        valueOf(nacosPropertiesAttributes)));
            }
        }
    
        if (!StringUtils.hasText(name)) {
            name = buildDefaultPropertySourceName(dataId, groupId, nacosProperties);
        }
    
        NacosPropertySource nacosPropertySource = new NacosPropertySource(name, nacosConfig);
    
        nacosPropertySource.setBeanName(beanName);
    
        String beanClassName = beanDefinition.getBeanClassName();
        if (StringUtils.hasText(beanClassName)) {
            nacosPropertySource.setBeanType(resolveClassName(beanClassName, classLoader));
        }
        nacosPropertySource.setGroupId(groupId);
        nacosPropertySource.setDataId(dataId);
        nacosPropertySource.setProperties(nacosProperties);
    
        initNacosPropertySource(nacosPropertySource, beanDefinition, runtimeAttributes);
    
        return nacosPropertySource;
    
    }
    
    // com.alibaba.nacos.spring.util.config.NacosConfigLoader#load(java.lang.String, java.lang.String, java.util.Properties)
    public String load(String dataId, String groupId, Properties nacosProperties) throws RuntimeException {
        try {
            configService = nacosServiceFactory != null ?
                    nacosServiceFactory.createConfigService(nacosProperties) :
                    NacosFactory.createConfigService(nacosProperties);
        } catch (NacosException e) {
            throw new RuntimeException("ConfigService can't be created with dataId :"
                    + dataId + " , groupId : " + groupId + " , properties : " + nacosProperties
                    , e);
        }
        return NacosUtils.getContent(configService, dataId, groupId);
    }
    
    // com.alibaba.nacos.spring.util.NacosUtils#getContent
    public static String getContent(ConfigService configService, String dataId, String groupId) {
        String content = null;
        try {
            content = configService.getConfig(dataId, groupId, DEFAULT_TIMEOUT);
        } catch (NacosException e) {
            if (logger.isErrorEnabled()) {
                logger.error("Can't get content from dataId : " + dataId + " , groupId : " + groupId, e);
            }
        }
        return content;
    }
  • 相关阅读:
    AdvDataList分页 例码
    问一个关于生成静态页面的问题
    使用XMLDataSource简单实现多级下拉菜单
    简单的封装一个HTML 弹出对话框的空间
    JS 语言强大, 动态修改标准库
    Eclipse IDE 学习
    分布式程序的开发
    Http request Post pk Put
    Forward: X Forwarding with Putty on Windows
    转载: 颠覆了对于design 的认识
  • 原文地址:https://www.cnblogs.com/allenwas3/p/12492635.html
Copyright © 2020-2023  润新知