在spring cloud 服务发现之Eureka Client(一)—客户端配置DEMO章节中介绍了如何快速的启动一个Eureka Client, 并将当前服务信息注册到Eureka Server中。在这篇文章中,将主要介绍在Eureka Client自动状态的过程中,需要执行那些过程,那些类是在启动过程中比不可少了。
这篇文章中,主要介绍通用的使用过程,其他的装配过程基本类似。
EnableDiscoveryClient
该类作为通用的服务发现客户端的启用类,可以用作不同的服务发现组件。该类源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
/**
* If true, the ServiceRegistry will automatically register the local server.
* @return - {@code true} if you want to automatically register.
*/
boolean autoRegister() default true;
}
通过该类的源码可以看到,该类型通过Import引入了EnableDiscoveryClientImportSelector类型,该类型主要是对EnableDiscoveryClient 注解的解析和配置。
EnableDiscoveryClientImportSelector
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector
extends SpringFactoryImportSelector<EnableDiscoveryClient> {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
String[] imports = super.selectImports(metadata);
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
// 判断是否auto register
boolean autoRegister = attributes.getBoolean("autoRegister");
if (autoRegister) {
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
// 自动引入AutoServiceRegistrationConfiguration
importsList.add(
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
imports = importsList.toArray(new String[0]);
}
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;
}
}
通过Import的方式,引入了新的配置AutoServiceRegistrationConfiguration类型。
AutoServiceRegistrationConfiguration
@Configuration
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class AutoServiceRegistrationConfiguration {
}
该类主要是判断spring.cloud.service-registry.auto-registration.enabled的配置信息是否启用服务自动注册功能,并引入配置类AutoServiceRegistrationProperties.
注解的功能整体到该类就截止了,整体并没有特殊的功能,主要就是加载必要的配置类型,生成Properties配置文件。
AutoServiceRegistrationAutoConfiguration
@Configuration
@Import(AutoServiceRegistrationConfiguration.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class AutoServiceRegistrationAutoConfiguration {
@Autowired(required = false)
private AutoServiceRegistration autoServiceRegistration;
@Autowired
private AutoServiceRegistrationProperties properties;
@PostConstruct
protected void init() {
if (this.autoServiceRegistration == null && this.properties.isFailFast()) {
throw new IllegalStateException("Auto Service Registration has "
+ "been requested, but there is no AutoServiceRegistration bean");
}
}
}
这是一个装配类型,该类型的启动,主要依赖于spring.cloud.service-registry.auto-registration.enabled配置的值,在缺省情况下为true。在该类中,主要会依赖注入两个类型,AutoServiceRegistrationProperties 与AutoServiceRegistration 类型,下面主要看下AutoServiceRegistration 类型,该类在什么地方被创建?
EurekaDiscoveryClientConfigServiceBootstrapConfiguration
在Spring boot 启动过程中会扫描spring.factories文件,并加载文件中的配置内容,在Spring cloud commons中,有如下配置:
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceBootstrapConfiguration
查看该类的配置源码:
@ConditionalOnClass(ConfigServicePropertySourceLocator.class)
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
@Configuration
@Import({ EurekaDiscoveryClientConfiguration.class, // this emulates
// @EnableDiscoveryClient, the import
// selector doesn't run before the
// bootstrap phase
EurekaClientAutoConfiguration.class })
public class EurekaDiscoveryClientConfigServiceBootstrapConfiguration {
}
该类被启动有两个条件:
ConfigServicePropertySourceLocator类必须存在spring.cloud.config.discovery.enabled启动
当以上两个条件满足时, 该类才会启动配置, 在装配的过程中,主要设计到两个配置对象: EurekaDiscoveryClientConfiguration 与 EurekaClientAutoConfiguration
EurekaDiscoveryClientConfiguration
查看该类源码:
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
public class EurekaDiscoveryClientConfiguration {
@Bean
public Marker eurekaDiscoverClientMarker() {
return new Marker();
}
@Configuration
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled", matchIfMissing = false)
protected static class EurekaHealthCheckHandlerConfiguration {
@Autowired(required = false)
private HealthAggregator healthAggregator = new OrderedHealthAggregator();
@Bean
@ConditionalOnMissingBean(HealthCheckHandler.class)
public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
return new EurekaHealthCheckHandler(this.healthAggregator);
}
}
class Marker {
}
@Configuration
@ConditionalOnClass(RefreshScopeRefreshedEvent.class)
protected static class EurekaClientConfigurationRefresher
implements ApplicationListener<RefreshScopeRefreshedEvent> {
@Autowired(required = false)
private EurekaClient eurekaClient;
@Autowired(required = false)
private EurekaAutoServiceRegistration autoRegistration;
public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
// This will force the creation of the EurkaClient bean if not already created
// to make sure the client will be reregistered after a refresh event
if (eurekaClient != null) {
eurekaClient.getApplications();
}
if (autoRegistration != null) {
// register in case meta data changed
this.autoRegistration.stop();
this.autoRegistration.start();
}
}
}
}
该装配类型生效,需要满足一下条件:
- 在
classpath中必须要引入EurekaClientConfig类型 - 启用配置
eureka.client.enabled, 默认值为true - 启用
spring.cloud.config.discovery.enabled配置,默认值为true
该配置类型主要做了两件事情:
- 生成
Marker对象,在Eureka Server装配时,也是通过Marker对象来启动装配的,因此这个Marker也是作为开关使用 - 根据
eureka.client.healthcheck.enabled默认值为false,如果为true,则开启EurekaHealthCheckHandler类型 - 生成
EurekaClientConfigurationRefresherBean, 用于处理RefreshScopeRefreshedEvent事件.
EurekaClientAutoConfiguration
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@Import(DiscoveryClientOptionalArgsConfiguration.class)
@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })
@AutoConfigureAfter(name = {
"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration",
"org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration",
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" })
首先需要关注该装配类型什么时候能够生效, 当前类型生效需要满足以下条件:
- 在
classpath环境中能够找到EurekaClientConfig类型 - 需要依赖
EurekaDiscoveryClientConfiguration中生成MarkerBean对象。 - 需要启用配置
eureka.client.enabled,默认值为true - 需要启用配置
spring.cloud.discovery.enabled,默认为true
当环境中满足以上权限时,则EurekaClientAutoConfiguration自动装配开始,在装配开始前,主要包含了:
- 引入
DiscoveryClientOptionalArgsConfiguration配置类型 AutoConfigureBefore配置了当前配置完成后,继续配置NoopDiscoveryClientAutoConfiguration,CommonsClientAutoConfiguration,ServiceRegistryAutoConfiguration装配类型AutoConfigureAfter装配开始前,则需要引入RefreshAutoConfiguration,EurekaDiscoveryClientConfiguration,AutoServiceRegistrationAutoConfiguration类型
DiscoveryClientOptionalArgsConfiguration
该类型从命名上可知,这是一个可选项,源码如下:
@Configuration
public class DiscoveryClientOptionalArgsConfiguration {
@Bean
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs() {
return new RestTemplateDiscoveryClientOptionalArgs();
}
@Bean
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
return new MutableDiscoveryClientOptionalArgs();
}
}
该类型主要是配置DiscoveryClient使用,在缺少AbstractDiscoveryClientOptionalArgs对象时,能够生成对应对象,用于存储参数信息。
前置装配 – RefreshAutoConfiguration
在装配开始前,将优先配置该类, 该类具体源码如下:
@Configuration
@ConditionalOnClass(RefreshScope.class)
@ConditionalOnProperty(name = RefreshAutoConfiguration.REFRESH_SCOPE_ENABLED, matchIfMissing = true)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
public class RefreshAutoConfiguration {
/**
* Name of the refresh scope name.
*/
public static final String REFRESH_SCOPE_NAME = "refresh";
/**
* Name of the prefix for refresh scope.
*/
public static final String REFRESH_SCOPE_PREFIX = "spring.cloud.refresh";
/**
* Name of the enabled prefix for refresh scope.
*/
public static final String REFRESH_SCOPE_ENABLED = REFRESH_SCOPE_PREFIX + ".enabled";
@Bean
@ConditionalOnMissingBean(RefreshScope.class)
public static RefreshScope refreshScope() {
return new RefreshScope();
}
@Bean
@ConditionalOnMissingBean
public static LoggingRebinder loggingRebinder() {
return new LoggingRebinder();
}
@Bean
@ConditionalOnMissingBean
public ContextRefresher contextRefresher(ConfigurableApplicationContext context,
RefreshScope scope) {
return new ContextRefresher(context, scope);
}
@Bean
public RefreshEventListener refreshEventListener(ContextRefresher contextRefresher) {
return new RefreshEventListener(contextRefresher);
}
@Configuration
@ConditionalOnClass(name = "javax.persistence.EntityManagerFactory")
protected static class JpaInvokerConfiguration implements LoadTimeWeaverAware {
@Autowired
private ListableBeanFactory beanFactory;
@PostConstruct
public void init() {
String cls = "org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker";
if (this.beanFactory.containsBean(cls)) {
this.beanFactory.getBean(cls);
}
}
@Override
public void setLoadTimeWeaver(LoadTimeWeaver ltw) {
}
}
....
}
该类型主要是对spring cloud中RefreshScope相关的配置信息, 这里不错探讨
前置装配-EurekaDiscoveryClientConfiguration
该类前面已经详细说过,这里就不再讲述了
前置装配-AutoServiceRegistrationAutoConfiguration
该类前面也已经讲述过了,这里也不在讲述.
装配中-EurekaClientConfigBean
@Bean
@ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
public EurekaClientConfigBean eurekaClientConfigBean(ConfigurableEnvironment env) {
EurekaClientConfigBean client = new EurekaClientConfigBean();
if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {
// We don't register during bootstrap by default, but there will be another
// chance later.
client.setRegisterWithEureka(false);
}
return client;
}
该类主要是实现EurekaClient配置对象,该类是基于EurekaClientConfig进行二次封装, 主要由spring实现。在properties中的eureka.client前缀配置信息,最终会被解析为当前对象。
装配中-ManagementMetadataProvider
@Bean
@ConditionalOnMissingBean
public ManagementMetadataProvider serviceManagementMetadataProvider() {
return new DefaultManagementMetadataProvider();
}
该类主要对Instance中的元数据信息进行管理,
装配中-InetUtils
这个类型是Spring提供的一个工具类,该类的自动注入是放在spring-cloud-commons模块中,通过UtilAutoConfiguration类型进行装配,源码如下:
@Configuration
@ConditionalOnProperty(value = "spring.cloud.util.enabled", matchIfMissing = true)
@AutoConfigureOrder(0)
@EnableConfigurationProperties
public class UtilAutoConfiguration {
@Bean
public InetUtilsProperties inetUtilsProperties() {
return new InetUtilsProperties();
}
@Bean
@ConditionalOnMissingBean
public InetUtils inetUtils(InetUtilsProperties properties) {
return new InetUtils(properties);
}
}
该类的装配实现中,依赖spring.cloud.util.enabled的配置信息,该配置信息默认true
装配中-EurekaInstanceConfigBean
@Bean
@ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT)
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils,
ManagementMetadataProvider managementMetadataProvider) {
// 当前实例hostName
String hostname = getProperty("eureka.instance.hostname");
// prefer-ip-address配置
boolean preferIpAddress = Boolean
.parseBoolean(getProperty("eureka.instance.prefer-ip-address"));
// 读取ip-address配置
String ipAddress = getProperty("eureka.instance.ip-address");
// 读取secure-port-enabled配置
boolean isSecurePortEnabled = Boolean
.parseBoolean(getProperty("eureka.instance.secure-port-enabled"));
// 获取servlet context-path信息
String serverContextPath = env.getProperty("server.servlet.context-path", "/");
// 获取port信息
int serverPort = Integer.parseInt(
env.getProperty("server.port", env.getProperty("port", "8080")));
// 获取management信息
Integer managementPort = env.getProperty("management.server.port", Integer.class);
// 获取management servlet context-path信息
String managementContextPath = env
.getProperty("management.server.servlet.context-path");
// 获取jmx 中remote port信息
Integer jmxPort = env.getProperty("com.sun.management.jmxremote.port",Integer.class);
// 初始化ConfigBean对象,该对象在初始化过程中, 将会获取当前服务的实例信息
EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
instance.setNonSecurePort(serverPort);
instance.setInstanceId(getDefaultInstanceId(env));
instance.setPreferIpAddress(preferIpAddress);
instance.setSecurePortEnabled(isSecurePortEnabled);
if (StringUtils.hasText(ipAddress)) {
instance.setIpAddress(ipAddress);
}
if (isSecurePortEnabled) {
instance.setSecurePort(serverPort);
}
if (StringUtils.hasText(hostname)) {
instance.setHostname(hostname);
}
// 获取status-page-url-path信息
String statusPageUrlPath = getProperty("eureka.instance.status-page-url-path");
// 获取health-check-url-path信息
String healthCheckUrlPath = getProperty("eureka.instance.health-check-url-path");
if (StringUtils.hasText(statusPageUrlPath)) {
instance.setStatusPageUrlPath(statusPageUrlPath);
}
if (StringUtils.hasText(healthCheckUrlPath)) {
instance.setHealthCheckUrlPath(healthCheckUrlPath);
}
// 获取与management 相关的信息组装
ManagementMetadata metadata = managementMetadataProvider.get(instance, serverPort,
serverContextPath, managementContextPath, managementPort);
if (metadata != null) {
instance.setStatusPageUrl(metadata.getStatusPageUrl());
instance.setHealthCheckUrl(metadata.getHealthCheckUrl());
if (instance.isSecurePortEnabled()) {
instance.setSecureHealthCheckUrl(metadata.getSecureHealthCheckUrl());
}
Map<String, String> metadataMap = instance.getMetadataMap();
metadataMap.computeIfAbsent("management.port",
k -> String.valueOf(metadata.getManagementPort()));
}
else {
// without the metadata the status and health check URLs will not be set
// and the status page and health check url paths will not include the
// context path so set them here
if (StringUtils.hasText(managementContextPath)) {
instance.setHealthCheckUrlPath(
managementContextPath + instance.getHealthCheckUrlPath());
instance.setStatusPageUrlPath(
managementContextPath + instance.getStatusPageUrlPath());
}
}
setupJmxPort(instance, jmxPort);
return instance;
}
该方法其实是为了组装EurekaInstanceConfigBean 对象信息,该对象信息是通过前置配置eureka.instance.*进行配置。该类型在配置换完成之后,则包含了默认的配置信息。
在初始化EurekaInstanceConfigBean 对象时,传入的参数中需要InetUtil对象作为参数, 我们看下该类主要用处:
public EurekaInstanceConfigBean(InetUtils inetUtils) {
this.inetUtils = inetUtils;
this.hostInfo = this.inetUtils.findFirstNonLoopbackHostInfo();
this.ipAddress = this.hostInfo.getIpAddress();
this.hostname = this.hostInfo.getHostname();
}
从代码中不难看出,在初始化bean时,主要需要赋值三个元素:
- 获取当前服务实例的hostInfo信息
- 获取当前服务实例的ipAddress信息
- 获取当前服务实例的hostname信息
这三个信息都是通过inetutils.findFirstNonLoopbackHostInfo()中进行获取,具体查看下该方法中执行逻辑:
public HostInfo findFirstNonLoopbackHostInfo() {
InetAddress address = findFirstNonLoopbackAddress();
if (address != null) {
return convertAddress(address);
}
HostInfo hostInfo = new HostInfo();
hostInfo.setHostname(this.properties.getDefaultHostname());
hostInfo.setIpAddress(this.properties.getDefaultIpAddress());
return hostInfo;
}
public InetAddress findFirstNonLoopbackAddress() {
InetAddress result = null;
try {
int lowest = Integer.MAX_VALUE;
// 获取当前实例下的所有绑定IP地址列表
for (Enumeration<NetworkInterface> nics = NetworkInterface
.getNetworkInterfaces(); nics.hasMoreElements();) {
NetworkInterface ifc = nics.nextElement();
// 判断当前的network interface是否处于UP并且处于running状态
if (ifc.isUp()) {
this.log.trace("Testing interface: " + ifc.getDisplayName());
if (ifc.getIndex() < lowest || result == null) {
lowest = ifc.getIndex();
}
else if (result != null) {
continue;
}
// @formatter:off
if (!ignoreInterface(ifc.getDisplayName())) {
for (Enumeration<InetAddress> addrs = ifc
.getInetAddresses(); addrs.hasMoreElements();) {
InetAddress address = addrs.nextElement();
if (address instanceof Inet4Address
&& !address.isLoopbackAddress() // 判断是否为循环IP地址, 该类IP地址主要由软件实现
&& isPreferredAddress(address)) {
this.log.trace("Found non-loopback interface: "
+ ifc.getDisplayName());
result = address;
}
}
}
// @formatter:on
}
}
}
catch (IOException ex) {
this.log.error("Cannot get first non-loopback address", ex);
}
if (result != null) {
return result;
}
try {
// 如果默认没有获取到IP地址,则使用本地地址作为IP地址
return InetAddress.getLocalHost();
}
catch (UnknownHostException e) {
this.log.warn("Unable to retrieve localhost");
}
return null;
}
装配中-EurekaServiceRegistry
@Bean
public EurekaServiceRegistry eurekaServiceRegistry() {
return new EurekaServiceRegistry();
}
装配中-ApplicationInfoManager
@Bean
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public ApplicationInfoManager eurekaApplicationInfoManager(
EurekaInstanceConfig config) {
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
return new ApplicationInfoManager(config, instanceInfo);
}
该类主要依赖了前面的EurekaInstanceConfigBean对象,然后通过create方法创建InstanceInfo信息,然后再通过ApplicationInfoManager进行管理当前实例信息.
装配中-EurekaClient
该类作为主要核心类,则主要负责与Eureka Server进行通信,并获取Applications列表, 该类装配实现是在RefreshableEurekaClientConfiguration中实现,因为我们当前处于spring-cloud的环境中,依赖于refresh scope的实现。具体代码如下
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public EurekaClient eurekaClient(ApplicationInfoManager manager,
EurekaClientConfig config, EurekaInstanceConfig instance,
@Autowired(required = false) HealthCheckHandler healthCheckHandler) {
// If we use the proxy of the ApplicationInfoManager we could run into a
// problem
// when shutdown is called on the CloudEurekaClient where the
// ApplicationInfoManager bean is
// requested but wont be allowed because we are shutting down. To avoid this
// we use the
// object directly.
ApplicationInfoManager appManager;
if (AopUtils.isAopProxy(manager)) {
appManager = ProxyUtils.getTargetObject(manager);
}
else {
appManager = manager;
}
CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager,
config, this.optionalArgs, this.context);
cloudEurekaClient.registerHealthCheck(healthCheckHandler);
return cloudEurekaClient;
}
在创建EurekaClient对象时,主要使用了CloudEurekaClient对象实现了原始netflix的EurekaClient的实现,同时注册HealthCheckHandler对象。保证EurekaClient正常的运作。
装配中-EurekaRegistration
该类主要保存了当前服务实例的注册信息,具体源码如下:
@Bean
@org.springframework.cloud.context.config.annotation.RefreshScope
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
CloudEurekaInstanceConfig instanceConfig,
ApplicationInfoManager applicationInfoManager,
@Autowired(required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager)
.with(eurekaClient).with(healthCheckHandler).build();
}
通过以上信息可以看出, 当前类型生效的有一下前提:
AutoServiceRegistrationPropertiesbean的存在,而该Bean则是通过EnableDiscoveryClient进行初始化- 开启
spring.cloud.service-registry.auto-registration.enabled配置信息,默认为true
通过以上信息可以看出,在默认情况下,该类是能够自动装配的。
装配中-EurekaAutoServiceRegistration
该类则是开启自动服务注册的入口,配置如下:
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(
ApplicationContext context, EurekaServiceRegistry registry,
EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
装配后置-NoopDiscoveryClientAutoConfiguration
该类已经被标记为废除,同时依赖于没有DiscoveryClient对象,通过以上步骤,会发现,当前装配类不会执行。
装配后置-CommonsClientAutoConfiguration
该类主要作为通用的DiscoveryClient的配置, 主要是配置HealIndicator对象,具体代码如下:
@Configuration
@AutoConfigureOrder(0)
public class CommonsClientAutoConfiguration {
@Configuration
@EnableConfigurationProperties(DiscoveryClientHealthIndicatorProperties.class)
@ConditionalOnClass(HealthIndicator.class)
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnDiscoveryEnabled
protected static class DiscoveryLoadBalancerConfiguration {
@Bean
@ConditionalOnProperty(value = "spring.cloud.discovery.client.health-indicator.enabled", matchIfMissing = true)
public DiscoveryClientHealthIndicator discoveryClientHealthIndicator(
ObjectProvider<DiscoveryClient> discoveryClient,
DiscoveryClientHealthIndicatorProperties properties) {
return new DiscoveryClientHealthIndicator(discoveryClient, properties);
}
@Bean
@ConditionalOnProperty(value = "spring.cloud.discovery.client.composite-indicator.enabled", matchIfMissing = true)
@ConditionalOnBean({ DiscoveryHealthIndicator.class, HealthAggregator.class })
public DiscoveryCompositeHealthIndicator discoveryCompositeHealthIndicator(
HealthAggregator aggregator, List<DiscoveryHealthIndicator> indicators) {
return new DiscoveryCompositeHealthIndicator(aggregator, indicators);
}
@Bean
public HasFeatures commonsFeatures() {
return HasFeatures.abstractFeatures(DiscoveryClient.class,
LoadBalancerClient.class);
}
}
@Configuration
@ConditionalOnClass(Endpoint.class)
@ConditionalOnProperty(value = "spring.cloud.features.enabled", matchIfMissing = true)
protected static class ActuatorConfiguration {
@Autowired(required = false)
private List<HasFeatures> hasFeatures = new ArrayList<>();
@Bean
@ConditionalOnEnabledEndpoint
public FeaturesEndpoint featuresEndpoint() {
return new FeaturesEndpoint(this.hasFeatures);
}
}
}
装配后置-ServiceRegistryAutoConfiguration
该类主要是对ServiceRegistry的再次封装,返回ServiceRegistryEndpoint对象,具体配置如下:
@Configuration
public class ServiceRegistryAutoConfiguration {
@ConditionalOnBean(ServiceRegistry.class)
@ConditionalOnClass(Endpoint.class)
protected class ServiceRegistryEndpointConfiguration {
@Autowired(required = false)
private Registration registration;
@Bean
@ConditionalOnEnabledEndpoint
public ServiceRegistryEndpoint serviceRegistryEndpoint(
ServiceRegistry serviceRegistry) {
ServiceRegistryEndpoint endpoint = new ServiceRegistryEndpoint(
serviceRegistry);
endpoint.setRegistration(this.registration);
return endpoint;
}
}
}
以上就是Eureka Client整体装配过程,后面将对里面的细节进行详细的说明。
当我们有时候会发现会后的两个配置不会执行,是因为最后两项都是对registry的服务状态的暴露,因此需要我们引入spring-boot-starter-actuator之后,就能够正常执行了