必备知识:ImportBeanDefinitionRegistrar方式实现Bean的动态装载
1.FeignClient初始化
在ImportBeanDefinitionRegistrar方式实现Bean的动态装载 一文中,@EnableFeignClients 这个注解的作用是开启feignClient的扫描,注解定义如下:
package org.springframework.cloud.openfeign;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of {@code @ComponentScan(basePackages="org.my.pkg")}.
* @return the array of 'basePackages'.
*/
String[] value() default {
};
/**
* Base packages to scan for annotated components.
* @return the array of 'basePackages'.
*/
String[] basePackages() default {
};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components.
* @return the array of 'basePackageClasses'.
*/
Class<?>[] basePackageClasses() default {
};
/**
* A custom <code>@Configuration</code> for all feign clients
* @return list of default configurations
*/
Class<?>[] defaultConfiguration() default {
};
/**
* List of classes annotated with @FeignClient. If not empty, disables classpath scanning.
* @return list of FeignClient classes
*/
Class<?>[] clients() default {
};
}
其中**@Import(FeignClientsRegistrar.class)** 导入了一个配置类FeignClientsRegistrar,这个类实现了ImportBeanDefinitionRegistrar接口,那么必然要重写接口中的registerBeanDefinitions 方法:
//AnnotationMetadata metadata:注解中的元数据
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
registerDefaultConfiguration(metadata, registry); // 注册默认的配置信息,
registerFeignClients(metadata, registry); // 注册不同包下所有的FeignClient
}
这个方法里面又做了两件事:
- registerDefaultConfiguration(metadata, registry)
- registerFeignClients(metadata, registry)
public void registerFeignClients(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {
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");
if (clients == null || clients.length == 0) {
scanner.addIncludeFilter(annotationTypeFilter);
basePackages = getBasePackages(metadata);
}
else {
final Set<String> clientClasses = new HashSet<>();
basePackages = new HashSet<>();
for (Class<?> clazz : clients) {
basePackages.add(ClassUtils.getPackageName(clazz))