Talk about the featuresEndpoint of springcloud

sequence

This article mainly studies the featuresEndpoint of springcloud

/actuator/features

{
  "enabled": [
    {
      "type": "com.netflix.discovery.EurekaClient",
      "name": "Eureka Client",
      "version": "1.8.8",
      "vendor": null
    },
    {
      "type": "org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient",
      "name": "DiscoveryClient",
      "version": "2.0.0.RC1",
      "vendor": "Pivotal Software, Inc."
    },
    {
      "type": "org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient",
      "name": "LoadBalancerClient",
      "version": "2.0.0.RC1",
      "vendor": "Pivotal Software, Inc."
    },
    {
      "type": "com.netflix.ribbon.Ribbon",
      "name": "Ribbon",
      "version": "2.2.5",
      "vendor": null
    },
    {
      "type": "feign.Feign",
      "name": "Feign",
      "version": null,
      "vendor": null
    }
  ],
  "disabled": []
}

CommonsClientAutoConfiguration

spring-cloud-commons-2.0.0.RC1-sources.jar!/org/springframework/cloud/client/CommonsClientAutoConfiguration.java

@Configuration
@AutoConfigureOrder(0)
public class CommonsClientAutoConfiguration {

	@Configuration
	@EnableConfigurationProperties(DiscoveryClientHealthIndicatorProperties.class)
	@ConditionalOnClass(HealthIndicator.class)
	@ConditionalOnBean(DiscoveryClient.class)
	@ConditionalOnProperty(value = "spring.cloud.discovery.enabled", matchIfMissing = true)
	protected static class DiscoveryLoadBalancerConfiguration {
		@Bean
		@ConditionalOnProperty(value = "spring.cloud.discovery.client.health-indicator.enabled", matchIfMissing = true)
		public DiscoveryClientHealthIndicator discoveryClientHealthIndicator(
				DiscoveryClient discoveryClient, DiscoveryClientHealthIndicatorProperties properties) {
			return new DiscoveryClientHealthIndicator(discoveryClient, properties);
		}

		@Bean
		@ConditionalOnProperty(value = "spring.cloud.discovery.client.composite-indicator.enabled", matchIfMissing = true)
		@ConditionalOnBean(DiscoveryHealthIndicator.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);
		}
	}

}

Here is an ActuatorConfiguration to register featuresEndpoint

FeaturesEndpoint

spring-cloud-commons-2.0.0.RC1-sources.jar!/org/springframework/cloud/client/actuator/FeaturesEndpoint.java

@Endpoint(id = "features")
public class FeaturesEndpoint
		implements ApplicationContextAware {

	private final List<HasFeatures> hasFeaturesList;
	private ApplicationContext context;

	public FeaturesEndpoint(List<HasFeatures> hasFeaturesList) {
		this.hasFeaturesList = hasFeaturesList;
	}

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		this.context = context;
	}

	@ReadOperation
	public Features features() {
		Features features = new Features();

		for (HasFeatures hasFeatures : this.hasFeaturesList) {
			List<Class<?>> abstractFeatures = hasFeatures.getAbstractFeatures();
			if (abstractFeatures != null) {
				for (Class<?> clazz : abstractFeatures) {
					addAbstractFeature(features, clazz);
				}
			}

			List<NamedFeature> namedFeatures = hasFeatures.getNamedFeatures();
			if (namedFeatures != null) {
				for (NamedFeature namedFeature : namedFeatures) {
					addFeature(features, namedFeature);
				}
			}
		}

		return features;
	}

	private void addAbstractFeature(Features features, Class<?> type) {
		String featureName = type.getSimpleName();
		try {
			Object bean = this.context.getBean(type);
			Class<?> beanClass = bean.getClass();
			addFeature(features, new NamedFeature(featureName, beanClass));
		}
		catch (NoSuchBeanDefinitionException e) {
			features.getDisabled().add(featureName);
		}
	}

	private void addFeature(Features features, NamedFeature feature) {
		Class<?> type = feature.getType();
		features.getEnabled()
				.add(new Feature(feature.getName(), type.getCanonicalName(),
						type.getPackage().getImplementationVersion(),
						type.getPackage().getImplementationVendor()));
	}
    //......
}

Here, two types of features are assembled through hasFeaturesList, one is abstractFeatures, and the other is namedFeatures

HasFeatures

spring-cloud-commons-2.0.0.RC1-sources.jar!/org/springframework/cloud/client/actuator/HasFeatures.java

public class HasFeatures {

	private final List<Class<?>> abstractFeatures = new ArrayList<>();

	private final List<NamedFeature> namedFeatures = new ArrayList<>();

	public static HasFeatures abstractFeatures(Class<?>... abstractFeatures) {
		return new HasFeatures(Arrays.asList(abstractFeatures),
				Collections.<NamedFeature> emptyList());
	}

	public static HasFeatures namedFeatures(NamedFeature... namedFeatures) {
		return new HasFeatures(Collections.<Class<?>> emptyList(),
				Arrays.asList(namedFeatures));
	}

	public static HasFeatures namedFeature(String name, Class<?> type) {
		return namedFeatures(new NamedFeature(name, type));
	}

	public static HasFeatures namedFeatures(String name1, Class<?> type1, String name2,
			Class<?> type2) {
		return namedFeatures(new NamedFeature(name1, type1),
				new NamedFeature(name2, type2));
	}

	public HasFeatures(List<Class<?>> abstractFeatures,
			List<NamedFeature> namedFeatures) {
		this.abstractFeatures.addAll(abstractFeatures);
		this.namedFeatures.addAll(namedFeatures);
	}

	public List<Class<?>> getAbstractFeatures() {
		return this.abstractFeatures;
	}

	public List<NamedFeature> getNamedFeatures() {
		return this.namedFeatures;
	}
}

Two types of features are defined here, one is abstractFeatures and the other is namedFeatures

HasFeatures instance

spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar!/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java

@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@Import(DiscoveryClientOptionalArgsConfiguration.class)
@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@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"})
public class EurekaClientAutoConfiguration {

	private ConfigurableEnvironment env;

	public EurekaClientAutoConfiguration(ConfigurableEnvironment env) {
		this.env = env;
	}

	@Bean
	public HasFeatures eurekaFeature() {
		return HasFeatures.namedFeature("Eureka Client", EurekaClient.class);
	}
    //......
}

For example, the client of eureka registers a namedFeature named Eureka Client

summary

The featuresEndpoint provided by springcloud can facilitate us to view some features of the system startup, and then understand the system features.

doc

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325053711&siteId=291194637