前一陣看到有篇部落格說cloud從Edgware版本開始,可以不加@EnableDiscoveryClient註解,只要配置好註冊中心的相關配置即可自動開啟服務註冊功能,比較好奇其中的原理,研究了一番特意記錄下來
環境:
SpringBoot: 2.3.5
SpringCloud: Hoxton.SR8
SpringCloudAlibaba: 2.2.3
先看一下@EnableDiscoveryClient註解,只有一個屬性:autoRegister, 預設為true
@SpringBootApplication @EnableDiscoveryClient(autoRegister = true) public class NacosApplication { public static void main(String[] args) { SpringApplication.run(NacosApplication.class, args); } }
內部資訊(程式碼裡只保留了重點)
@Import(EnableDiscoveryClientImportSelector.class) public @interface EnableDiscoveryClient { boolean autoRegister() default true; }
EnableDiscoveryClientImportSelector
@Override public String[] selectImports(AnnotationMetadata metadata) { String[] imports = super.selectImports(metadata); AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(getAnnotationClass().getName(), true)); //獲取@EnableDiscoveryClient的autoRegister屬性 boolean autoRegister = attributes.getBoolean("autoRegister"); //開啟自動註冊的話,將AutoServiceRegistrationConfiguration類的全限定名返回,會被spring載入到bean容器 if (autoRegister) { List<String> importsList = new ArrayList<>(Arrays.asList(imports)); importsList.add( "org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration"); imports = importsList.toArray(new String[0]); } //關閉自動註冊的話,將***.auto-registration.enabled設定為false,放入環境屬性中(其他地方會用到) else { Environment env = getEnvironment(); if (ConfigurableEnvironment.class.isInstance(env)) { ConfigurableEnvironment configEnv = (ConfigurableEnvironment) env; LinkedHashMap<String, Object> map = new LinkedHashMap<>(); map.put("spring.cloud.service-registry.auto-registration.enabled", false); MapPropertySource propertySource = new MapPropertySource( "springCloudDiscoveryClient", map); configEnv.getPropertySources().addLast(propertySource); } } return imports; }
AutoServiceRegistrationConfiguration是實現自動註冊的入口,具體的邏輯在由註冊中心實現(如Nacos\Eureka...)
//當**.registration.enabled屬性為true時,此配置類會被載入 //spring-cloud-commons.jar包內的spring-configuration-metadata.json定義了此屬性預設為true //即: 不配置@EnableDiscoveryClient或者配置@EnableDiscoveryClient設定autoRegister為true時 //AutoServiceRegistrationConfiguration會被載入,當@EnableDiscoveryClient的autoRegister //為false時,此配置類不會被載入 @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(AutoServiceRegistrationProperties.class) @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) public class AutoServiceRegistrationConfiguration { }
Nacos實現邏輯
配置:
spring: application: name: nacosTest cloud: nacos: discovery: enabled: true(預設為true,可以不配置) server-addr: 192.168.1.10 port: 8848 username: nacos password: nacos
spring-cloud-starter-alibaba-nacos-discovery.jar/META-INF/spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\
com.alibaba.cloud.nacos.ribbon.RibbonNacosAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration
開啟NacosServiceRegistryAutoConfiguration.java, 內部實現了服務自動註冊邏輯
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties //確保spring.cloud.nacos.discovery.enabled為true(開啟nacos的服務註冊與發現功能) @ConditionalOnNacosDiscoveryEnabled //預設為true,只有開啟了@EnableDiscoveryClient註解,並且配置autoRegister為false時, //此屬性值才為false @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) @AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class, NacosDiscoveryAutoConfiguration.class }) public class NacosServiceRegistryAutoConfiguration { @Bean public NacosServiceRegistry nacosServiceRegistry( NacosDiscoveryProperties nacosDiscoveryProperties) { return new NacosServiceRegistry(nacosDiscoveryProperties); } @Bean @ConditionalOnBean(AutoServiceRegistrationProperties.class) public NacosRegistration nacosRegistration( ObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers, NacosDiscoveryProperties nacosDiscoveryProperties, ApplicationContext context) { return new NacosRegistration(registrationCustomizers.getIfAvailable(), nacosDiscoveryProperties, context); } @Bean @ConditionalOnBean(AutoServiceRegistrationProperties.class) public NacosAutoServiceRegistration nacosAutoServiceRegistration( NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) { return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration); } }
最後測試:
配置 |
是否成功註冊到註冊中心 |
不配置@EnableDiscoveryClient,不配置nacos.discovery.enable |
是 |
不配置@EnableDiscoveryClient,配置nacos.discovery.enable=false |
否 |
配置@EnableDiscoveryClient,配置nacos.discovery.enable=true |
是 |
配置@EnableDiscoveryClient,配置nacos.discovery.enable=false |
否 |
配置@EnableDiscoveryClient(autoRegister=false),配置nacos.discovery.enable=true |
否 |
配置@EnableDiscoveryClient(autoRegister=false),配置nacos.discovery.enable=false |
否 |