added @EnableCircuitBreaker and SingleImplementationImportSelector
This commit is contained in:
11
pom.xml
11
pom.xml
@@ -59,6 +59,12 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
@@ -69,6 +75,11 @@
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import static org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration.ManagementServerPort;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class ManagementServerPortUtils {
|
||||
|
||||
public static ManagementServerPort get(BeanFactory beanFactory) {
|
||||
return ManagementServerPort.get(beanFactory);
|
||||
}
|
||||
|
||||
public static boolean isDifferent(BeanFactory beanFactory) {
|
||||
return get(beanFactory) == ManagementServerPort.DIFFERENT;
|
||||
}
|
||||
|
||||
public static boolean isDisabled(BeanFactory beanFactory) {
|
||||
return get(beanFactory) == ManagementServerPort.DISABLE;
|
||||
}
|
||||
|
||||
public static boolean isSame(BeanFactory beanFactory) {
|
||||
return get(beanFactory) == ManagementServerPort.SAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.springframework.cloud.client;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.context.annotation.DeferredImportSelector;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Selects a single configuration to load defined by the generic type T.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class SingleImplementationImportSelector<T> implements DeferredImportSelector, BeanClassLoaderAware {
|
||||
|
||||
protected ClassLoader beanClassLoader;
|
||||
|
||||
protected Class<T> annotationClass;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected SingleImplementationImportSelector() {
|
||||
annotationClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(this.getClass(), SingleImplementationImportSelector.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata metadata) {
|
||||
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata
|
||||
.getAnnotationAttributes(annotationClass.getName(),
|
||||
true));
|
||||
|
||||
Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is "
|
||||
+ metadata.getClassName() + " annotated with @" + getSimpleName() + "?");
|
||||
|
||||
// Find all possible auto configuration classes, filtering duplicates
|
||||
List<String> factories = new ArrayList<>(new LinkedHashSet<>(
|
||||
SpringFactoriesLoader.loadFactoryNames(annotationClass,
|
||||
this.beanClassLoader)));
|
||||
|
||||
if (factories.size() > 1) {
|
||||
String factory = factories.get(0);
|
||||
//there should only every be one DiscoveryClient
|
||||
log.warn("More than one implementation of @{}. Using {} out of available {}", getSimpleName(), factory, factories);
|
||||
factories = Collections.singletonList(factory);
|
||||
}
|
||||
|
||||
return factories.toArray(new String[factories.size()]);
|
||||
|
||||
}
|
||||
|
||||
protected String getSimpleName() {
|
||||
return annotationClass.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.cloud.client.circuitbreaker;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(EnableCircuitBreakerImportSelector.class)
|
||||
public @interface EnableCircuitBreaker {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.springframework.cloud.client.circuitbreaker;
|
||||
|
||||
import org.springframework.cloud.client.SingleImplementationImportSelector;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 100)
|
||||
public class EnableCircuitBreakerImportSelector extends SingleImplementationImportSelector<EnableCircuitBreaker> {
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.springframework.cloud.client.discovery;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.actuate.autoconfigure.ManagementServerPortUtils;
|
||||
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
@@ -1,60 +1,13 @@
|
||||
package org.springframework.cloud.client.discovery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.context.annotation.DeferredImportSelector;
|
||||
import org.springframework.cloud.client.SingleImplementationImportSelector;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 100)
|
||||
@Slf4j
|
||||
public class EnableDiscoveryClientImportSelector implements DeferredImportSelector,
|
||||
BeanClassLoaderAware {
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata metadata) {
|
||||
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata
|
||||
.getAnnotationAttributes(EnableDiscoveryClient.class.getName(),
|
||||
true));
|
||||
|
||||
Assert.notNull(attributes, "No EnableDiscoveryClient attributes found. Is "
|
||||
+ metadata.getClassName()
|
||||
+ " annotated with @EnableDiscoveryClient?");
|
||||
|
||||
// Find all possible auto configuration classes, filtering duplicates
|
||||
List<String> factories = new ArrayList<>(new LinkedHashSet<>(
|
||||
SpringFactoriesLoader.loadFactoryNames(EnableDiscoveryClient.class,
|
||||
this.beanClassLoader)));
|
||||
|
||||
if (factories.size() > 1) {
|
||||
String factory = factories.get(0);
|
||||
//there should only every be one DiscoveryClient
|
||||
log.warn("More than one implementation of @EnableDiscoveryClient. Using {} out of available {}", factory, factories);
|
||||
factories = Collections.singletonList(factory);
|
||||
}
|
||||
|
||||
return factories.toArray(new String[factories.size()]);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
public class EnableDiscoveryClientImportSelector extends SingleImplementationImportSelector<EnableDiscoveryClient> {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.springframework.cloud.client.discovery;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class ManagementServerPortUtils {
|
||||
|
||||
//TODO: copied from EndpointWebMvcAutoConfiguration.ManagementServerPort
|
||||
public static enum ManagementServerPort {
|
||||
|
||||
DISABLE, SAME, DIFFERENT;
|
||||
|
||||
public static ManagementServerPort get(BeanFactory beanFactory) {
|
||||
|
||||
ServerProperties serverProperties;
|
||||
try {
|
||||
serverProperties = beanFactory.getBean(ServerProperties.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
serverProperties = new ServerProperties();
|
||||
}
|
||||
|
||||
ManagementServerProperties managementServerProperties;
|
||||
try {
|
||||
managementServerProperties = beanFactory
|
||||
.getBean(ManagementServerProperties.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
managementServerProperties = new ManagementServerProperties();
|
||||
}
|
||||
|
||||
Integer port = managementServerProperties.getPort();
|
||||
if (port != null && port < 0) {
|
||||
return DISABLE;
|
||||
}
|
||||
if (!(beanFactory instanceof WebApplicationContext)) {
|
||||
// Current context is not a webapp
|
||||
return DIFFERENT;
|
||||
}
|
||||
return ((port == null)
|
||||
|| (serverProperties.getPort() == null && port.equals(8080))
|
||||
|| (port != 0 && port.equals(serverProperties.getPort())) ? SAME
|
||||
: DIFFERENT);
|
||||
}
|
||||
};
|
||||
|
||||
public static ManagementServerPort get(BeanFactory beanFactory) {
|
||||
return ManagementServerPort.get(beanFactory);
|
||||
}
|
||||
|
||||
public static boolean isDifferent(BeanFactory beanFactory) {
|
||||
return get(beanFactory) == ManagementServerPort.DIFFERENT;
|
||||
}
|
||||
|
||||
public static boolean isDisabled(BeanFactory beanFactory) {
|
||||
return get(beanFactory) == ManagementServerPort.DISABLE;
|
||||
}
|
||||
|
||||
public static boolean isSame(BeanFactory beanFactory) {
|
||||
return get(beanFactory) == ManagementServerPort.SAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.cloud.client;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class SingleImplementationImportSelectorTests {
|
||||
|
||||
@Test
|
||||
public void testFindAnnotation() {
|
||||
MyAnnotationImportSelector selector = new MyAnnotationImportSelector();
|
||||
assertEquals("annotationClass was wrong", MyAnnotation.class, selector.annotationClass);
|
||||
}
|
||||
|
||||
public static @interface MyAnnotation {}
|
||||
public static class MyAnnotationImportSelector extends SingleImplementationImportSelector<MyAnnotation> { }
|
||||
}
|
||||
Reference in New Issue
Block a user