added @EnableCircuitBreaker and SingleImplementationImportSelector

This commit is contained in:
Spencer Gibb
2014-12-02 14:43:20 -07:00
parent d80b02dfe2
commit f96d9947df
9 changed files with 196 additions and 77 deletions

11
pom.xml
View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
}

View File

@@ -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> {
}

View File

@@ -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;

View File

@@ -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> {
}

View File

@@ -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;
}
}

View File

@@ -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> { }
}