一,找到启动类的注解:@EnableFeignClients
找到服务消费者上启动类的@EnableFeignClients
@SpringBootApplication
@EntityScan("com.zjk.order.entity")
@EnableEurekaClient
//通过@EnableFeignClients 激活feign
@EnableFeignClients
public class OrderApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
二,点击去@EnableFeignClients 这个类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] defaultConfiguration() default {};
Class<?>[] clients() default {};
}
三,找到EnableFeignClients 类的@Import({FeignClientsRegistrar.class})
点击去FeignClientsRegistrar类,可以看到实现的ImportBeanDefinitionRegistrar接口,实现这个接口就要复写该接口的registerBeanDefinitions()方法。
registerBeanDefinitions()方法调用了两个方法。其中着重看registerFeignClients()方法。
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
private ResourceLoader resourceLoader;
private Environment environment;
public FeignClientsRegistrar() {
}
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
this.registerDefaultConfiguration(metadata, registry);
this.registerFeignClients(metadata, registry);
}
四,registerFeignClients()方法
registerFeignClients()方法中79行,
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);
- 可以看到,该行是查整个项目中是否有引用FeignClient注解的方法,自然的会找到我们自定义的feign 接口,
- 然后通过第122行的this.registerFeignClient(registry, annotationMetadata, attributes);将自定义的内容注册到spring中
- 查看registerFeignClient()方法。会找到FeignClientFactoryBean对象
五,FeignClientFactoryBean 对象
- FeignClientFactoryBean 对象中找到231行,target()方法
- 找到DefaultTarget类,找到16行的target()方法,点进去
- 找到207行newInstance()方法
- 然后在ReflectiveFeign类的60行找到InvocationHandler类。InvocationHandler对象是Java 动态代理必不可少的类。
- 然后点进去60行的create()方法,InvocationHandlerFactory对象中的21行,FeignInvocationHandler对象,这个对象就是我们最终找的对象。
不过这套没有弄通,主要是通过动态代理的方式,
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
scanner.setResourceLoader(this.resourceLoader);
Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);
Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
Object basePackages;
if (clients != null && clients.length != 0) {
final Set<String> clientClasses = new HashSet();
basePackages = new HashSet();
Class[] var9 = clients;
int var10 = clients.length;
for(int var11 = 0; var11 < var10; ++var11) {
Class<?> clazz = var9[var11];
((Set)basePackages).add(ClassUtils.getPackageName(clazz));
clientClasses.add(clazz.getCanonicalName());
}
AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
protected boolean match(ClassMetadata metadata) {
String cleaned = metadata.getClassName().replaceAll("\\$", ".");
return clientClasses.contains(cleaned);
}
};
scanner.addIncludeFilter(new FeignClientsRegistrar.AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));
} else {
scanner.addIncludeFilter(annotationTypeFilter);
basePackages = this.getBasePackages(metadata);
}
Iterator var17 = ((Set)basePackages).iterator();
while(var17.hasNext()) {
String basePackage = (String)var17.next();
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
Iterator var21 = candidateComponents.iterator();
while(var21.hasNext()) {
BeanDefinition candidateComponent = (BeanDefinition)var21.next();
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
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 name = this.getClientName(attributes);
this.registerClientConfiguration(registry, name, attributes.get("configuration"));
this.registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}
自定义feign 接口:
//指定需要调用的服务名称
@FeignClient(name = "service-product")
public interface productFeignHttpClient {
//调用的请求路径
@RequestMapping(value = "/product/{Id}",method = RequestMethod.GET)
public TbProduct findById(@PathVariable("Id") Long Id);
}
this.registerFeignClient(registry, annotationMetadata, attributes);方法
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
this.validate(attributes);
definition.addPropertyValue("url", this.getUrl(attributes));
definition.addPropertyValue("path", this.getPath(attributes));
String name = this.getName(attributes);
definition.addPropertyValue("name", name);
String contextId = this.getContextId(attributes);
definition.addPropertyValue("contextId", contextId);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(2);
String alias = contextId + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
boolean primary = (Boolean)attributes.get("primary");
beanDefinition.setPrimary(primary);
String qualifier = this.getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}