Commit bad20d3f by Spencer Gibb

Migrate SpringClientFactory and FeignClientFactory

Now uses spring-cloud-context NamedContextFactory. see https://github.com/spring-cloud/spring-cloud-commons/issues/69
parent 493caec5
...@@ -16,114 +16,20 @@ ...@@ -16,114 +16,20 @@
package org.springframework.cloud.netflix.feign; package org.springframework.cloud.netflix.feign;
import java.util.Collection; import org.springframework.cloud.context.named.NamedContextFactory;
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;
/** /**
* A factory that creates client, load balancer and client configuration instances. It * A factory that creates instances of feign classes. It * creates a Spring
* creates a Spring ApplicationContext per client name, and extracts the beans that it * ApplicationContext per client name, and extracts the beans that it
* needs from there. * needs from there.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @author Dave Syer * @author Dave Syer
*/ */
public class FeignClientFactory implements DisposableBean, ApplicationContextAware { public class FeignClientFactory extends NamedContextFactory<FeignClientSpecification> {
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
private Map<String, FeignClientSpecification> configurations = new ConcurrentHashMap<>();
private ApplicationContext parent;
@Override
public void setApplicationContext(ApplicationContext parent) throws BeansException {
this.parent = parent;
}
public void setConfigurations(List<FeignClientSpecification> configurations) {
for (FeignClientSpecification client : configurations) {
this.configurations.put(client.getName(), client);
}
}
@Override
public void destroy() {
Collection<AnnotationConfigApplicationContext> 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<String, FeignClientSpecification> 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.<String, Object> 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> C getInstance(String name, Class<C> type) {
AnnotationConfigApplicationContext context = getContext(name);
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
type).length > 0) {
return context.getBean(type);
}
return null;
}
public <C> Map<String, C> getInstances(String name, Class<C> type) { public FeignClientFactory() {
AnnotationConfigApplicationContext context = getContext(name); super(FeignClientsConfiguration.class, "feign", "feign.client.name");
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
type).length > 0) {
return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);
}
return null;
} }
} }
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package org.springframework.cloud.netflix.feign; package org.springframework.cloud.netflix.feign;
import org.springframework.cloud.context.named.NamedContextFactory;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
...@@ -26,7 +28,7 @@ import lombok.NoArgsConstructor; ...@@ -26,7 +28,7 @@ import lombok.NoArgsConstructor;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class FeignClientSpecification { public class FeignClientSpecification implements NamedContextFactory.Specification {
private String name; private String name;
......
...@@ -16,15 +16,19 @@ ...@@ -16,15 +16,19 @@
package org.springframework.cloud.netflix.ribbon; package org.springframework.cloud.netflix.ribbon;
import org.springframework.cloud.context.named.NamedContextFactory;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
/** /**
* @author Dave Syer * @author Dave Syer
*/ */
@Data @Data
@AllArgsConstructor @AllArgsConstructor
public class RibbonClientSpecification { @NoArgsConstructor
public class RibbonClientSpecification implements NamedContextFactory.Specification {
private String name; private String name;
......
...@@ -16,22 +16,9 @@ ...@@ -16,22 +16,9 @@
package org.springframework.cloud.netflix.ribbon; 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.BeanUtils;
import org.springframework.beans.BeansException; import org.springframework.cloud.context.named.NamedContextFactory;
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.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.MapPropertySource;
import com.netflix.client.IClient; import com.netflix.client.IClient;
import com.netflix.client.IClientConfigAware; import com.netflix.client.IClientConfigAware;
...@@ -46,32 +33,10 @@ import com.netflix.loadbalancer.ILoadBalancer; ...@@ -46,32 +33,10 @@ import com.netflix.loadbalancer.ILoadBalancer;
* @author Spencer Gibb * @author Spencer Gibb
* @author Dave Syer * @author Dave Syer
*/ */
public class SpringClientFactory implements DisposableBean, ApplicationContextAware { public class SpringClientFactory extends NamedContextFactory<RibbonClientSpecification> {
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
private Map<String, RibbonClientSpecification> configurations = new ConcurrentHashMap<>();
private ApplicationContext parent;
@Override
public void setApplicationContext(ApplicationContext parent) throws BeansException {
this.parent = parent;
}
public void setConfigurations(List<RibbonClientSpecification> configurations) { public SpringClientFactory() {
for (RibbonClientSpecification client : configurations) { super(RibbonClientConfiguration.class, "ribbon", "ribbon.client.name");
this.configurations.put(client.getName(), client);
}
}
@Override
public void destroy() {
Collection<AnnotationConfigApplicationContext> values = this.contexts.values();
this.contexts.clear();
for (AnnotationConfigApplicationContext context : values) {
context.close();
}
} }
/** /**
...@@ -106,51 +71,8 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw ...@@ -106,51 +71,8 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
return getInstance(serviceId, RibbonLoadBalancerContext.class); 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<String, RibbonClientSpecification> 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.<String, Object> 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> C instantiateWithConfig(AnnotationConfigApplicationContext context, private <C> C instantiateWithConfig(AnnotationConfigApplicationContext context,
Class<C> clazz, IClientConfig config) { Class<C> clazz, IClientConfig config) {
C result = null; C result = null;
if (IClientConfigAware.class.isAssignableFrom(clazz)) { if (IClientConfigAware.class.isAssignableFrom(clazz)) {
IClientConfigAware obj = (IClientConfigAware) BeanUtils.instantiate(clazz); IClientConfigAware obj = (IClientConfigAware) BeanUtils.instantiate(clazz);
...@@ -178,12 +100,13 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw ...@@ -178,12 +100,13 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
} }
public <C> C getInstance(String name, Class<C> type) { public <C> C getInstance(String name, Class<C> type) {
AnnotationConfigApplicationContext context = getContext(name); C instance = super.getInstance(name, type);
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0) { if (instance != null) {
return context.getBean(type); return instance;
} }
IClientConfig config = getInstance(name, IClientConfig.class); IClientConfig config = getInstance(name, IClientConfig.class);
return instantiateWithConfig(context, type, config); return instantiateWithConfig(getContext(name), type, config);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment