话不多说上代码
注解代码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(FeignAnnotationUpdateRegistrar.class)
public @interface AEnableUpdateFeignRegistrar {
/**
* 需要修改 扫描的包,默认会使用当前类上面的EnableFeignClients里头的包
* @return
*/
String[] value() default {"net","com"};
}
反射修改类的代码
@Slf4j
public class FeignAnnotationUpdateRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
private ResourceLoader resourceLoader;
private Environment environment;
private final Map<String, String> map = MapUtil.builder("scrm-component-server", "scrm-comonent-pro")
.put("scrm-user", "tcloud-user-pro").put("scrm-crm-customer", "tcloud-customer-pro")
// todo 这里添加需要替换的微服务名和网关对应的负载均衡名(也可动态修改为url,需要改动点代码,找到使用这个map的地方修改下)
.put("scrm-paas-common", "http://*******")
.map();
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
Set<String> basePackages = this.getBasePackages(metadata);
Iterator var8 = basePackages.iterator();
LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet();
while (var8.hasNext()) {
String basePackage = (String) var8.next();
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
for (BeanDefinition definition : candidateComponents) {
try {
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)definition;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
MergedAnnotations annotations = annotationMetadata.getAnnotations();
Class<?> feignClass = Class.forName(beanDefinition.getBeanClassName());
FeignClient feignClient = feignClass.getAnnotation(FeignClient.class);
Object value = feignClient.value();
String url = this.map.get(value);
if (url != null) {
InvocationHandler h = Proxy.getInvocationHandler(feignClient);
// 获取 AnnotationInvocationHandler 的 memberValues 字段
Field hField = h.getClass().getDeclaredField("memberValues");
// 因为这个字段事 private final 修饰,所以要打开权限
hField.setAccessible(true);
// 获取 memberValues
Map memberValues = (Map) hField.get(h);
// 修改 value 属性值
memberValues.put("url",url);
}
for (MergedAnnotation<Annotation> annotation : annotations) {
Class<Annotation> aClass = annotation.getType();
if (aClass.isAssignableFrom(FeignClient.class)) {
Class<? extends MergedAnnotation> annotationClass = annotation.getClass();
Field rootAttributes = annotationClass.getDeclaredField("rootAttributes");
rootAttributes.setAccessible(true);
Object attributes = rootAttributes.get(annotation);
if (attributes instanceof Map) {
Map<String, String> map = (Map<String, String>) attributes;
Object value = map.get("value");
String url = this.map.get(value);
if (url != null) {
// 这里就是替换feignClient注解里头的url,后面的值可以自定义填写
map.put("url", "https://preapiconsole.71360.com/api/app/" + url);
}
}
}
}
}
} catch (Exception e) {
log.error("反射修改feign的url失败", e);
}
}
}
private ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent() && !beanDefinition.getMetadata().isAnnotation()) {
isCandidate = true;
}
return isCandidate;
}
};
}
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(EnableFeignClients.class.getCanonicalName());
Set<String> basePackages = new HashSet();
String[] var4 = (String[]) ((String[]) attributes.get("value"));
int var5 = var4.length;
int var6;
String pkg;
for (var6 = 0; var6 < var5; ++var6) {
pkg = var4[var6];
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
var4 = (String[]) ((String[]) attributes.get("basePackages"));
var5 = var4.length;
for (var6 = 0; var6 < var5; ++var6) {
pkg = var4[var6];
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
Class[] var8 = (Class[]) ((Class[]) attributes.get("basePackageClasses"));
var5 = var8.length;
for (var6 = 0; var6 < var5; ++var6) {
Class<?> clazz = var8[var6];
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
}
return basePackages;
}
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
特别需要注意的事项:
EnableUpdateFeignRegistrar 这个注解必须要放到EnableFeignClients前头
如下
6月29 更新,可能会有从其它地方引入的feign导致修改不到 比如在其它的配置类中加EnableFeignClients,或者用Import
所以在注解中加了value,value中的包都会被扫描然后反射修改注解的值,从根源上解决问题