关于@EnableFeignClients的认识
今天起了大早,偶尔发现,项目忘记加入注解@EnableFeignClients,导致启动失败,于是想知道它做了啥呢?为什么项目没有加载相关bean?原来@EnableFeignClients是通过@Import把FeignClientsRegistrar注入到IOC容器中,当项目启动执行invokeBeanFactoryPostProcessors--》invokeBeanDefinitionRe
今天起了大早,偶发现,项目忘记加入注解@EnableFeignClients,导致启动失败,于是想知道它做了啥呢?为什么项目没有加载相关bean?
原来@EnableFeignClients是通过@Import把FeignClientsRegistrar注入到IOC容器中,当项目启动执行
invokeBeanFactoryPostProcessors--》
invokeBeanDefinitionRegistryPostProcessors—》
ConfigurationClassPostProcessor调用processConfigBeanDefinitions方法执行parser.parse(candidates)的时候会调用扫描解析类ClassPathBeanDefinitionScanner默认扫描并默认加载启动项包下的所有class(这里出现了个疑问,是否系统只注册@Component注解的类,这个问题一会看下代码),之后在执行reader.loadBeanDefinitions的时候会调用其他注册器进行注册--》
ConfigurationClassBeanDefinitionReader有两个方法,loadBeanDefinitionsFromImportedResources和loadBeanDefinitionsFromRegistrars,而本次使用的是loadBeanDefinitionsFromRegistrars,具体执行的注册器是FeignClientsRegistrar
注册过程FeignClientsRegistrar
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);
// 省略。。。。
for (String basePackage : basePackages) {
Set<BeanDefinition> candidateComponents = scanner
.findCandidateComponents(basePackage);
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
// 省略。。。。
// 这里找到客户端FeignClient注解,准备注册到 DefaultListableBeanFactory容器里
Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(
FeignClient.class.getCanonicalName());
String name = getClientName(attributes);
registerClientConfiguration(registry, name,
attributes.get("configuration"));
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);
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 });
// 注册Feign客户端到DefaultListableBeanFactory容器,这样启动后就能通过@Autowired注入,否则无法启动
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
ClassPathBeanDefinitionScanner分析是否系统只注册@Component注解的类
省略其中调用过程,直接进入ClassPathScanningCandidateComponentProvider分析doScan方法,紧接着进入scanCandidateComponents,顾名思义应该就是只注册@Component注解的类,
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
// 省略。。。。
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 过滤条件
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
// 省略。。。。
return candidates;
}
过滤条件中includeFileter包括Component:
确定给定的类是否与任何排除筛选器不匹配
与至少一个包含筛选器匹配。
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
更多推荐
所有评论(0)