|
|
@ -5,9 +5,7 @@ import java.util.HashSet; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
|
|
|
|
import lombok.Data; |
|
|
|
|
|
|
|
import org.springframework.beans.factory.BeanClassLoaderAware; |
|
|
|
import org.springframework.beans.factory.BeanClassLoaderAware; |
|
|
|
import org.springframework.beans.factory.FactoryBean; |
|
|
|
|
|
|
|
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; |
|
|
|
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; |
|
|
|
import org.springframework.beans.factory.config.BeanDefinition; |
|
|
|
import org.springframework.beans.factory.config.BeanDefinition; |
|
|
|
import org.springframework.beans.factory.config.BeanDefinitionHolder; |
|
|
|
import org.springframework.beans.factory.config.BeanDefinitionHolder; |
|
|
@ -50,29 +48,44 @@ public class FeignClientScanRegistrar extends FeignConfiguration |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { |
|
|
|
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { |
|
|
|
Map<String, Object> componentScan = importingClassMetadata |
|
|
|
|
|
|
|
.getAnnotationAttributes(FeignClientScan.class.getCanonicalName()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Set<String> basePackages = new HashSet<String>(); |
|
|
|
Set<String> basePackages = getBasePackages(importingClassMetadata); |
|
|
|
for (String pkg : (String[]) componentScan.get("value")) { |
|
|
|
|
|
|
|
if (StringUtils.hasText(pkg)) { |
|
|
|
ClassPathScanningCandidateComponentProvider scanner = getScanner(); |
|
|
|
basePackages.add(pkg); |
|
|
|
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class)); |
|
|
|
|
|
|
|
scanner.setResourceLoader(resourceLoader); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (String basePackage : basePackages) { |
|
|
|
|
|
|
|
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage); |
|
|
|
|
|
|
|
for (BeanDefinition candidateComponent : candidateComponents) { |
|
|
|
|
|
|
|
if (candidateComponent instanceof AnnotatedBeanDefinition) { |
|
|
|
|
|
|
|
//verify annotated class is an interface
|
|
|
|
|
|
|
|
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent; |
|
|
|
|
|
|
|
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata(); |
|
|
|
|
|
|
|
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BeanDefinitionHolder holder = createBeanDefinition(annotationMetadata); |
|
|
|
|
|
|
|
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
for (String pkg : (String[]) componentScan.get("basePackages")) { |
|
|
|
|
|
|
|
if (StringUtils.hasText(pkg)) { |
|
|
|
|
|
|
|
basePackages.add(pkg); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
for (Class<?> clazz : (Class[]) componentScan.get("basePackageClasses")) { |
|
|
|
|
|
|
|
basePackages.add(ClassUtils.getPackageName(clazz)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (basePackages.isEmpty()) { |
|
|
|
public BeanDefinitionHolder createBeanDefinition(AnnotationMetadata annotationMetadata) { |
|
|
|
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName())); |
|
|
|
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String className = annotationMetadata.getClassName(); |
|
|
|
|
|
|
|
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class); |
|
|
|
|
|
|
|
definition.addPropertyValue("loadbalance", attributes.get("loadbalance")); |
|
|
|
|
|
|
|
definition.addPropertyValue("type", className); |
|
|
|
|
|
|
|
definition.addPropertyValue("schemeName", attributes.get("value")); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String beanName = StringUtils.uncapitalize(className.substring(className.lastIndexOf(".") + 1)); |
|
|
|
|
|
|
|
return new BeanDefinitionHolder(definition.getBeanDefinition(), beanName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) { |
|
|
|
protected ClassPathScanningCandidateComponentProvider getScanner() { |
|
|
|
|
|
|
|
return new ClassPathScanningCandidateComponentProvider(false) { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { |
|
|
|
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { |
|
|
@ -95,61 +108,31 @@ public class FeignClientScanRegistrar extends FeignConfiguration |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scanner.setResourceLoader(resourceLoader); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (String basePackage : basePackages) { |
|
|
|
|
|
|
|
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage); |
|
|
|
|
|
|
|
for (BeanDefinition candidateComponent : candidateComponents) { |
|
|
|
|
|
|
|
if (candidateComponent instanceof AnnotatedBeanDefinition) { |
|
|
|
|
|
|
|
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent; |
|
|
|
|
|
|
|
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignFactoryBean.class); |
|
|
|
|
|
|
|
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata(); |
|
|
|
|
|
|
|
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String className = annotationMetadata.getClassName(); |
|
|
|
|
|
|
|
definition.addPropertyValue("loadbalance", attributes.get("loadbalance")); |
|
|
|
|
|
|
|
definition.addPropertyValue("type", className); |
|
|
|
|
|
|
|
definition.addPropertyValue("schemeName", attributes.get("value")); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String beanName = StringUtils.uncapitalize(className.substring(className.lastIndexOf(".")+1)); |
|
|
|
|
|
|
|
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition.getBeanDefinition(), beanName); |
|
|
|
|
|
|
|
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Data |
|
|
|
|
|
|
|
public static class FeignFactoryBean extends FeignConfiguration implements FactoryBean<Object> { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boolean loadbalance; |
|
|
|
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) { |
|
|
|
Class<?> type; |
|
|
|
Map<String, Object> attributes = importingClassMetadata |
|
|
|
String schemeName; |
|
|
|
.getAnnotationAttributes(FeignClientScan.class.getCanonicalName()); |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
Set<String> basePackages = new HashSet<>(); |
|
|
|
public Object getObject() throws Exception { |
|
|
|
for (String pkg : (String[]) attributes.get("value")) { |
|
|
|
if (!schemeName.startsWith("http")) { |
|
|
|
if (StringUtils.hasText(pkg)) { |
|
|
|
schemeName = "http://"+schemeName; |
|
|
|
basePackages.add(pkg); |
|
|
|
} |
|
|
|
} |
|
|
|
if (loadbalance) { |
|
|
|
|
|
|
|
return loadBalance(type, schemeName); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return feign().target(type, schemeName); |
|
|
|
for (String pkg : (String[]) attributes.get("basePackages")) { |
|
|
|
|
|
|
|
if (StringUtils.hasText(pkg)) { |
|
|
|
|
|
|
|
basePackages.add(pkg); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
@Override |
|
|
|
for (Class<?> clazz : (Class[]) attributes.get("basePackageClasses")) { |
|
|
|
public Class<?> getObjectType() { |
|
|
|
basePackages.add(ClassUtils.getPackageName(clazz)); |
|
|
|
return type; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
if (basePackages.isEmpty()) { |
|
|
|
public boolean isSingleton() { |
|
|
|
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName())); |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return basePackages; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|