Spring-Cloud-Starter-Alibaba-Nacos-Discovery 源码分析

本文深入探讨了Spring Cloud Alibaba Nacos Discovery的源码,从Spring Boot的@EnableDiscoveryClient开始,详细解释了如何启用服务发现。接着分析了Spring Cloud Commons中的@EnableDiscoveryClient注解和AutoServiceRegistrationConfiguration的自动服务注册配置。进一步,文章讲解了NacosDiscoveryClientConfigServiceBootstrapConfiguration在启动过程中的作用,以及NacosDiscoveryAutoConfiguration如何创建和管理NacosDiscoveryProperties。最后,讨论了NacosAutoServiceRegistration如何监听和处理NacosDiscoveryInfoChangedEvent,实现服务的注册与管理。
摘要由CSDN通过智能技术生成

0 版本

  • spring-cloud-starter-alibaba-nacos-discovery 2021.0.1.0
  • spring-cloud-commons 3.1.1
  • spring-boot-starter-web 2.6.3

1 Spring Boot

1.1.@EnableDiscoveryClient , 启用服务发现

通过在Aplication 处添加该注解, 启用服务发现:

@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现
public class MsGatewayApplication {
   

这个注解 @EnableDiscoveryClient 是在Spring-Cloud-Commons里定义的

2 Spring-Cloud-Commons

2.1 @EnableDiscoveryClient: 通过注解导入 EnableDiscoveryClientImportSelector

查看该注解定义, 可以看到 @Import({EnableDiscoveryClientImportSelector.class}) ,这个注解会在启动时, 自动注入 EnableDiscoveryClientImportSelector


@Target({
   ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({
   EnableDiscoveryClientImportSelector.class}) // 通过注解导入 EnableDiscoveryClientImportSelector
public @interface EnableDiscoveryClient {
   
    boolean autoRegister() default true;
}

2.1.1 EnableDiscoveryClientImportSelector 启用服务发现客户端导入选择器

EnableDiscoveryClientImportSelector 的主要功能是导入需要的 AutoServiceRegistrationConfiguration (自动服务注册配置类) 或者 修改环境变量,这取决于 @EnableDiscoveryClient 里的 autoRegister 参数

根据 autoRegister(默认为true)判断:
 
如果为 true :     importsList.add(“org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration”) 是在引用列表里添加 org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration , 这个类是在 spring-coud-commons 项目里定义的
   
如果为 false :
map.put(“spring.cloud.service-registry.auto-registration.enabled”, false) 在环境变量中将 自动注册 设为 false
 

@Order(2147483547)
public class EnableDiscoveryClientImportSelector extends SpringFactoryImportSelector<EnableDiscoveryClient> {
   
    public EnableDiscoveryClientImportSelector() {
   
    }

    public String[] selectImports(AnnotationMetadata metadata) {
   
        String[] imports = super.selectImports(metadata);
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(this.getAnnotationClass().getName(), true));
        boolean autoRegister = attributes.getBoolean("autoRegister");
        // 是否自动注册服务 EnableDiscoveryClient.autoRegister default true
        if (autoRegister) {
   
            // 引用列表
	        List<String> importsList = new ArrayList(Arrays.asList(imports));
	        // 调用 spring-cloud-commons  里的 AutoServiceRegistrationConfiguration (自动服务注册配置)
            importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
            imports = (String[])importsList.toArray(new String[0]);
        } else {
   
            Environment env = this.getEnvironment();
            if (ConfigurableEnvironment.class.isInstance(env)) {
   
                ConfigurableEnvironment configEnv = (ConfigurableEnvironment)env;
                LinkedHashMap<String, Object> map = new LinkedHashMap();
                // 配置 spring.cloud.service-registry.auto-registration.enabled 为false,不启用自动注册服务
                map.put("spring.cloud.service-registry.auto-registration.enabled", false);
                MapPropertySource propertySource = new MapPropertySource("springCloudDiscoveryClient", map);
	            // 添加到环境变量
                configEnv.getPropertySources().addLast(propertySource);
            }
        }

        return imports;
    }
  
    // 根据 配置项 spring.cloud.discovery.enabled 判断是否启用服务发现,该配置项默认为true
    protected boolean isEnabled() {
   
        // 从环境变量中获取 spring.cloud.discovery.enabled  的布尔值,并且默认返回TRUE
        return (Boolean)this.getEnvironment().getProperty("spring.cloud.discovery.enabled", Boolean.class, Boolean.TRUE);
    }

    protected boolean hasDefaultFactory() {
   
        return true;
    }
}

2.2 AutoServiceRegistrationConfiguration 自动服务注册配置

@EnableConfigurationProperties(AutoServiceRegistrationProperties.class) :
该注解的意思是启用配置类 AutoServiceRegistrationProperties
 
@ConditionalOnProperty(value = “spring.cloud.service-registry.auto-registration.enabled”, matchIfMissing = true):
spring.cloud.service-registry.auto-registration.enabled 的配置项为 true 的时候该类才会启用, 属性 matchIfMissing = true 的意思是假如没有对该项进行配置, 则默认情况下相当于 true,也会启用该类

/**
 * @author Spencer Gibb
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class) // 启用配置 AutoServiceRegistrationProperties
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)  // spring.cloud.service-registry.auto-registration.enabled 的配置项为true的时候,才会启用, matchIfMissing = true 为该配置项如果未配置,也会启用该类
public class AutoServiceRegistrationConfiguration {
   

}

2.2.1 @EnableConfigurationProperties, 启用配置属性

AutoServiceRegistrationConfiguration @Import(EnableConfigurationPropertiesRegistrar.class):
导入了 EnableConfigurationPropertiesRegistrar (一个关于启用属性配置的注册器),该注册器会将 @EnableConfigurationProperties 里的 Class<?>[] value() 进行bean注册 (即对 AutoServiceRegistrationProperties 进行bean注册)

/**
 * Enable support for {@link ConfigurationProperties @ConfigurationProperties} annotated
 * beans. {@code @ConfigurationProperties} beans can be registered in the standard way
 * (for example using {@link Bean @Bean} methods) or, for convenience, can be specified
 * directly on this annotation.
 *
 * @author Dave Syer
 * @since 1.0.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EnableConfigurationPropertiesRegistrar.class)
public @interface EnableConfigurationProperties {
   
	
	// 验证器 BEAN 名称 
	/**
	 * The bean name of the configuration properties validator.
	 * @since 2.2.0
	 */
	String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";

	// 接收一个数组,数组类型为ClassType
	/**
	 * Convenient way to quickly register
	 * {@link ConfigurationProperties @ConfigurationProperties} annotated beans with
	 * Spring. Standard Spring Beans will also be scanned regardless of this value.
	 * @return {@code @ConfigurationProperties} annotated beans to register
	 */
	Class<?>[] value() default {
   };

}

2.2.3 EnableConfigurationPropertiesRegistrar

AutoServiceRegistrationProperties 是怎么被引入呢
这类实现了接口 ImportBeanDefinitionRegistrar , 重写了registerBeanDefinitions 方法,它在这里将之前的 AutoServiceRegistrationProperties 通过 ConfigurationPropertiesBeanRegistrar 注册到容器

/**
 * {@link ImportBeanDefinitionRegistrar} for
 * {@link EnableConfigurationProperties @EnableConfigurationProperties}.
 *
 * @author Phillip Webb
 * @author Andy Wilkinson
 */
class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegistrar {
   
 
	private static final String METHOD_VALIDATION_EXCLUDE_FILTER_BEAN_NAME = Conventions
			.getQualifiedAttributeName(EnableConfigurationPropertiesRegistrar.class, "methodValidationExcludeFilter");

	
	// 注册
	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   
		registerInfrastructureBeans(registry);
		registerMethodValidationExcludeFilter(registry);
		// new 一个ConfigurationPropertiesBean注册器
		ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
	
		getTypes(metadata).forEach(beanRegistrar::register);
		/* 类似:依次注册 getTypes 返回的Class集 
		getTypes(metadata).forEach( (item) -> {
			beanRegistrar.register(item)
		} )
		*/
	}

	// 获取EnableConfigurationProperties集
	private Set<Class<?>> getTypes(AnnotationMetadata metadata) {
   
		return metadata.getAnnotations().stream(EnableConfigurationProperties.class)
				// 合并
				.flatMap((annotation) -> Arrays.stream(annotation.getClassArray(MergedAnnotation.VALUE)))
				// 过滤空的class
				.filter((type) -> void.class != type)
				// 返回set
				.collect(Collectors.toSet());
	}
	
	static void registerInfrastructureBeans(BeanDefinitionRegistry registry) {
   
		ConfigurationPropertiesBindingPostProcessor.register(registry);
		BoundConfigurationProperties.register(registry);
	}

	// 注册方法验证排除过滤器
	static void registerMethodValidationExcludeFilter(BeanDefinitionRegistry registry) 
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值