I was a little busy when I just arrived at the new company, so I finally had time to learn source code in combination with SS teacher’s course this week. Come on, keep learning.

1. Feign startup process

Last time I looked at the starting process of Feign’s guess, now I’m going straight to the source code.

In the last series of pictures, I hope I don’t get carsick. In fact, I think it is very difficult to see the source code, especially to see other people’s blog articles, simply confused, I have this kind of problem. So I will learn while output, this is the best way to learn.

There is a key @import tag from the FeignClients annotation.

Go to the FeignClientsRegistrar class.

We can see FeignClientsRegistrar this class, the ImportBeanDefinitionRegistrar interface implementation

OK, then we call the FeignClientsRegistrar#registerBeanDefinitions method below to do a rewrite.

PS: Because when the Spring context starts, this method is called for initialization

OK, back to the text, start with the FeignClientsRegistrar#registerBeanDefinitions method

Ii. Analysis of registerBeanDefinitions

2.1 registerDefaultConfiguration(metadata, registry);

Directly on the code:

private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {// Get attrs attribute value on @enableFeignClients, Package to the corresponding Map in a Map < String, Object > defaultAttrs = metadata. GetAnnotationAttributes (EnableFeignClients. Class. GetName (), true); if (defaultAttrs ! = null && defaultAttrs.containsKey("defaultConfiguration")) { String name; if (metadata.hasEnclosingClass()) { name = "default." + metadata.getEnclosingClassName(); } else { name = "default." + metadata.getClassName(); } registerClientConfiguration(registry, name, defaultAttrs.get("defaultConfiguration")); }}Copy the code

There’s nothing particularly important here:

  1. Inject an attribute from the @enableFeignClients annotation into the Map.

Here need to focus on a key object: metadata getAnnotationAttributes (EnableFeignClients. Class. GetName (), true); Remark 1.

2.2 RegisterClients (Metadata, Registry) analysis

The code here is too long, it is difficult to pull all the code out at once, so the local analysis method is used here.

2.2.1 Scanning Properties
public void registerFeignClients(..) { ClassPathScanningCandidateComponentProvider scanner = getScanner(); scanner.setResourceLoader(this.resourceLoader); Set<String> basePackages; Map<String, Object> attrs = metadata .getAnnotationAttributes(EnableFeignClients.class.getName()); AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter( FeignClient.class); final Class<? >[] clients = attrs == null ? null : (Class<? >[]) attrs.get("clients"); } // omit the following code.... registerFeignClient(...)Copy the code

Focus on this line of code:

Map<String, Object> attrs = metadata
  			.getAnnotationAttributes(EnableFeignClients.class.getName());
Copy the code

We just mentioned that annotation 1 does this by dropping the attributes from the @enableFeignClients annotation onto the Map for saving.

Notice the following code:

Class<? >[] clients = attrs == null ? null : (Class<? >[]) attrs.get("clients");Copy the code

Get the class name annotated with @enableFeignClients. PS: Spring’s package sweep process follows, and the for loop assembles the corresponding bean into the container.

By the way, after the package is scanned, registerFeignClients is followed by a feignClient process.

2.2.2 registerFeignClients method analysis

The e code here is relatively simple, are to do some attribute assembly.

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) { String className = annotationMetadata.getClassName(); // This line of FeignClientFactoryBean needs to be paid special attention to BeanDefinitionBuilder definition = BeanDefinitionBuilder .genericBeanDefinition(FeignClientFactoryBean.class); validate(attributes); / / attributes into the 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 = new BeanDefinitionHolder(beanDefinition, className, new String[] { alias }); BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); }Copy the code

In this method, we need to focus on the following points:

BeanDefinitionBuilder definition = BeanDefinitionBuilder
   			.genericBeanDefinition(FeignClientFactoryBean.class);

Copy the code

That’s the FeignClientFactoryBean class. PS: This class is actually the core class generated by feign’s dynamic proxy.

At this point, Feign’s package scan has been analyzed. 1. Use the @enableFeign annotation to identify feign classes and inject their corresponding properties into containers for Spring to manage. 2. Focus on the FeignClientFactoryBean class, which is the key class for Feign dynamic proxy. Feign dynamic proxy is implemented through Feign dynamic proxy.