SpringCloud原理 OpenFeign之FeignClient动态代理生成原理二
接下来我分别剖析一下这两个方法的作用
registerClientConfiguration:
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
Object configuration) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientSpecification.class);
builder.addConstructorArgValue(name);
builder.addConstructorArgValue(configuration);
registry.registerBeanDefinition(
name + "." + FeignClientSpecification.class.getSimpleName(),
builder.getBeanDefinition());
}
这里的作用就是拿出你再@FeignClient指定的配置类,也就是configuration属性,然后构建一个bean class为FeignClientSpecification,传入配置。这个类的最主要作用就是将每个Feign的客户端的配置类封装成一个FeignClientSpecification的BeanDefinition,注册到spring容器中。记住这个FeignClientSpecification,后面会有用。
registerFeignClient:
private void registerFeignClient(BeanDefinitionRegistry registry,
AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
validate(attributes);
definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("path", getPath(attributes));
String name = getName(attributes);
definition.addPropertyValue("name", name);
String contextId = 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(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
String alias = contextId + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
boolean primary = (Boolean) attributes.get("primary"); // has a default, won't be
// null
beanDefinition.setPrimary(primary);
String qualifier = getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
new String[] { alias });
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
registerFeignClient这个方法很重要,我来说一下大概做了哪些事。重新构造了一个BeanDefinition,这个BeanDefinition的指定的class类型是FeignClientFactoryBean,这个类实现了FactoryBean接口,对spring有一定了解的小伙伴应该知道,spring在生成bean的时候,判断BeanDefinition中bean的class如果是FactoryBean的实现的话,会调用这个实现类的getObject来获取对象,这里我就不展开讲了,不了解的同学可以记住这个结论。
到这一步,@EnableFeignClinets的作用就说完了。这个类的主要作用是扫描指定(不指定就默认路径下的)所有加了@FeignClient注解的类,然后每个类都会生成一个BeanDefinition,随后遍历每个BeanDefinition,然后取出每个@FeignClient注解的属性,构造新的BeanDefinition,传入FeignClientFactoryBean的class,随后注入到spring容器中;同时有配置类的也会将配置类构件出一个bean class为FeignClientSpecification的BeanDefinition注入到spring容器中。
为了便于理解,我这里画个图来总结一下这个注解干了什么事。
文章转自公众号:三友的java日记