diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactory.java index bcfe63cc..7aa2e777 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactory.java @@ -16,114 +16,20 @@ package org.springframework.cloud.netflix.feign; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.core.env.MapPropertySource; +import org.springframework.cloud.context.named.NamedContextFactory; /** - * A factory that creates client, load balancer and client configuration instances. It - * creates a Spring ApplicationContext per client name, and extracts the beans that it + * A factory that creates instances of feign classes. It * creates a Spring + * ApplicationContext per client name, and extracts the beans that it * needs from there. * * @author Spencer Gibb * @author Dave Syer */ -public class FeignClientFactory implements DisposableBean, ApplicationContextAware { +public class FeignClientFactory extends NamedContextFactory { - private Map contexts = new ConcurrentHashMap<>(); - - private Map configurations = new ConcurrentHashMap<>(); - - private ApplicationContext parent; - - @Override - public void setApplicationContext(ApplicationContext parent) throws BeansException { - this.parent = parent; - } - - public void setConfigurations(List configurations) { - for (FeignClientSpecification client : configurations) { - this.configurations.put(client.getName(), client); - } - } - - @Override - public void destroy() { - Collection values = this.contexts.values(); - this.contexts.clear(); - for (AnnotationConfigApplicationContext context : values) { - context.close(); - } - } - - private AnnotationConfigApplicationContext getContext(String name) { - if (!this.contexts.containsKey(name)) { - synchronized (this.contexts) { - if (!this.contexts.containsKey(name)) { - this.contexts.put(name, createContext(name)); - } - } - } - return this.contexts.get(name); - } - - private AnnotationConfigApplicationContext createContext(String name) { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - if (this.configurations.containsKey(name)) { - for (Class configuration : this.configurations.get(name) - .getConfiguration()) { - context.register(configuration); - } - } - for (Entry entry : this.configurations - .entrySet()) { - if (entry.getKey().startsWith("default.")) { - for (Class configuration : entry.getValue().getConfiguration()) { - context.register(configuration); - } - } - } - context.register(PropertyPlaceholderAutoConfiguration.class, - FeignClientsConfiguration.class); - context.getEnvironment().getPropertySources().addFirst(new MapPropertySource( - "feign", - Collections. singletonMap("feign.client.name", name))); - if (this.parent != null) { - // Uses Environment from parent as well as beans - context.setParent(this.parent); - } - context.refresh(); - return context; - } - - public C getInstance(String name, Class type) { - AnnotationConfigApplicationContext context = getContext(name); - if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, - type).length > 0) { - return context.getBean(type); - } - return null; - } - - public Map getInstances(String name, Class type) { - AnnotationConfigApplicationContext context = getContext(name); - if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, - type).length > 0) { - return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type); - } - return null; + public FeignClientFactory() { + super(FeignClientsConfiguration.class, "feign", "feign.client.name"); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientSpecification.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientSpecification.java index 955dde42..07b0623b 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientSpecification.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientSpecification.java @@ -16,6 +16,8 @@ package org.springframework.cloud.netflix.feign; +import org.springframework.cloud.context.named.NamedContextFactory; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -26,7 +28,7 @@ import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor -public class FeignClientSpecification { +public class FeignClientSpecification implements NamedContextFactory.Specification { private String name; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientSpecification.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientSpecification.java index 7c492a5c..3187e2ba 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientSpecification.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientSpecification.java @@ -16,15 +16,19 @@ package org.springframework.cloud.netflix.ribbon; +import org.springframework.cloud.context.named.NamedContextFactory; + import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; /** * @author Dave Syer */ @Data @AllArgsConstructor -public class RibbonClientSpecification { +@NoArgsConstructor +public class RibbonClientSpecification implements NamedContextFactory.Specification { private String name; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java index cea2941c..6fc43d4d 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java @@ -16,22 +16,9 @@ package org.springframework.cloud.netflix.ribbon; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; - import org.springframework.beans.BeanUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; +import org.springframework.cloud.context.named.NamedContextFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.core.env.MapPropertySource; import com.netflix.client.IClient; import com.netflix.client.IClientConfigAware; @@ -46,32 +33,10 @@ import com.netflix.loadbalancer.ILoadBalancer; * @author Spencer Gibb * @author Dave Syer */ -public class SpringClientFactory implements DisposableBean, ApplicationContextAware { +public class SpringClientFactory extends NamedContextFactory { - private Map contexts = new ConcurrentHashMap<>(); - - private Map configurations = new ConcurrentHashMap<>(); - - private ApplicationContext parent; - - @Override - public void setApplicationContext(ApplicationContext parent) throws BeansException { - this.parent = parent; - } - - public void setConfigurations(List configurations) { - for (RibbonClientSpecification client : configurations) { - this.configurations.put(client.getName(), client); - } - } - - @Override - public void destroy() { - Collection values = this.contexts.values(); - this.contexts.clear(); - for (AnnotationConfigApplicationContext context : values) { - context.close(); - } + public SpringClientFactory() { + super(RibbonClientConfiguration.class, "ribbon", "ribbon.client.name"); } /** @@ -106,51 +71,8 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw return getInstance(serviceId, RibbonLoadBalancerContext.class); } - private AnnotationConfigApplicationContext getContext(String name) { - if (!this.contexts.containsKey(name)) { - synchronized (this.contexts) { - if (!this.contexts.containsKey(name)) { - this.contexts.put(name, createContext(name)); - } - } - } - return this.contexts.get(name); - } - - private AnnotationConfigApplicationContext createContext(String name) { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - if (this.configurations.containsKey(name)) { - for (Class configuration : this.configurations.get(name) - .getConfiguration()) { - context.register(configuration); - } - } - for (Entry entry : this.configurations - .entrySet()) { - if (entry.getKey().startsWith("default.")) { - for (Class configuration : entry.getValue().getConfiguration()) { - context.register(configuration); - } - } - } - context.register(PropertyPlaceholderAutoConfiguration.class, - RibbonClientConfiguration.class); - context.getEnvironment() - .getPropertySources() - .addFirst( - new MapPropertySource("ribbon", - Collections. singletonMap( - "ribbon.client.name", name))); - if (this.parent != null) { - // Uses Environment from parent as well as beans - context.setParent(this.parent); - } - context.refresh(); - return context; - } - private C instantiateWithConfig(AnnotationConfigApplicationContext context, - Class clazz, IClientConfig config) { + Class clazz, IClientConfig config) { C result = null; if (IClientConfigAware.class.isAssignableFrom(clazz)) { IClientConfigAware obj = (IClientConfigAware) BeanUtils.instantiate(clazz); @@ -178,12 +100,13 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw } public C getInstance(String name, Class type) { - AnnotationConfigApplicationContext context = getContext(name); - if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0) { - return context.getBean(type); + C instance = super.getInstance(name, type); + if (instance != null) { + return instance; } IClientConfig config = getInstance(name, IClientConfig.class); - return instantiateWithConfig(context, type, config); + return instantiateWithConfig(getContext(name), type, config); } } +