序
本文主要研究下springcloud的featuresEndpoint
/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);
}
}
}
这里有一个ActuatorConfiguration,用来注册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()));
}
//......
}
这里通过hasFeaturesList来组装两类features,一类是abstractFeatures,另外一类是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;
}
}
这里定义了两类features,一类是abstractFeatures,一类是namedFeatures
HasFeatures实例
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);
}
//......
}
比如eureka的client就注册了一个名为Eureka Client的namedFeature
小结
springcloud提供的featuresEndpoint,可以方便我们查看系统启动的一些features,进而了解系统特征。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。