返回顶部
首页 > 资讯 > 后端开发 > Python >@FeignClient注入找不到异常如何解决
  • 932
分享到

@FeignClient注入找不到异常如何解决

2024-04-02 19:04:59 932人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

前言 SpringCloud中的服务间调用是通过Feign进行调用的,在调用方服务中,我们需要定义一些带有@FeignClient注解的接口类。并且在启动类上加上@EnableFei

前言

SpringCloud中的服务间调用是通过Feign进行调用的,在调用方服务中,我们需要定义一些带有@FeignClient注解的接口类。并且在启动类上加上@EnableFeignClients注解。

程序启动的时候,会检查是否有@EnableFeignClients注解,如果有该注解,则开启包扫描,扫描带有@FeignClient注解的接口。

这里结合之前遇到的一个问题来和大家一起学习下@EnableFeignClients启动过程。

问题描述

之前搭建一个简单demo的时候,启动之后总是报错

Field client1Feign in com.aiqinhai.client2.controller.Testrequired a bean of type
'com.aiqinhai.client2.feignclient.Client1Feign' that could not be found.
Action:
Consider defining a bean of type 'com.aiqinhai.client2.feignclient.Client1Feign' in your configuration.
Process finished with exit code 1

排查了一顿之后,发现启动上的@EnableFeignClients注解,没有指定basePackages包扫描路径。

而且Client1Feign接口不是和启动类在同一目录下,所以启动的时候就会报上述错误。

后来在@EnableFeignClients指定了扫描包路径就解决了。


@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.aiqinhai.client2.feignclient"})
public class Client2Application {
    public static void main(String[] args) {
        springApplication.run(Client2Application.class, args);
    }
}

问题确实解决了,但是我们还是需要了解服务启动的时候,@EnableFeignClients注解干了哪些事。

刨根@EnableFeignClients

想了解清楚这个注解的作用,最好的方式就是看看注解的源码。点进去之后,可以看到



@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(FeignClientsReGIStrar.class)
public @interface EnableFeignClients {
 //同basePackages
 String[] value() default {};
        //扫描的package.
 String[] basePackages() default {};
 //feigin client全局配置,默认配置在FeignClientsConfiguration类中
 Class<?>[] defaultConfiguration() default {};
 //@FeignClient注解的接口,如果指定了该属性,则关闭扫描。
 Class<?>[] clients() default {};
}


可以看到,注解中import了FeignClientsRegistrar类,我们进去看看,可以看到包扫描的逻辑就是在FeignClientsRegistrar中实现的,会扫描所有的.class文件,过滤出@FeignClient标注的接口,然后通过BeanDefinitionBuilder生成FeignClientFactoryBean对象,注入到ioc容器中。

具体代码如下


class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
		ResourceLoaderAware, EnvironmentAware {
	//包扫描方法入口
	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
		//注册默认配置bean到ioc
		registerDefaultConfiguration(metadata, registry);
		//注册@FeignClients标注的接口bean,为其生成动态代理
		registerFeignClients(metadata, registry);
	}
	private void registerDefaultConfiguration(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
		//获取@EnableFeignClients注解属性
		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();
			}
			//注册@EnableFeignClients defaultConfiguration 类中定义的bean到ioc
			registerClientConfiguration(registry, name,
					defaultAttrs.get("defaultConfiguration"));		}
	}
	public void registerFeignClients(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
		//spring 扫描工具类
		ClassPathScanningCandidateComponentProvider scanner = getScanner();
		scanner.setResourceLoader(this.resourceLoader);
        //待扫描的包
		Set<String> basePackages;
        //@EnableFeignClients注解属性
		Map<String, Object> attrs = metadata
				.getAnnotationAttributes(EnableFeignClients.class.getName());
		//@FeignClient注解过滤器,只扫描@FeignClient注解标注的接口
		AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
				FeignClient.class);
		//解析@EnableFeignClient 属性clients
		final Class<?>[] clients = attrs == null ? null
				: (Class<?>[]) attrs.get("clients");
		//如果@EnableFeignClient没有指定clients,则开启包扫描,否则关闭扫描,使用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));
				clientClasses.add(clazz.getCanonicalName());
			}
			AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
				@Override
				protected boolean match(ClaSSMetadata metadata) {
					String cleaned = metadata.getClassName().replaceAll("\\$", ".");
					return clientClasses.contains(cleaned);
				}
			};
			scanner.addIncludeFilter(
					new AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));
		}
		for (String basePackage : basePackages) {
		    //从类路径下的所有.class文件中扫描@FeignClient注解的接口
			Set<BeanDefinition> candidateComponents = scanner
					.findCandidateComponents(basePackage);
			for (BeanDefinition candidateComponent : candidateComponents) {
				if (candidateComponent instanceof AnnotatedBeanDefinition) {
					// verify annotated class is an interface
					AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
					//获取注解
					AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
					//@FeignClient注解必须应用在接口上,否则抛出异常。
					Assert.isTrue(annotationMetadata.isInterface(),
							"@FeignClient can only be specified on an interface");
                        //获取FeignClient注解属性
					Map<String, Object> attributes = annotationMetadata
							.getAnnotationAttributes(
									FeignClient.class.getCanonicalName());
                        //服务名称
					String name = getClientName(attributes);
					//注册configuration中指定的bean
					registerClientConfiguration(registry, name,
							attributes.get("configuration"));
					//生成FeignClient bean,并注册到ioc
					registerFeignClient(registry, annotationMetadata, attributes);
				}
			}
		}
	}
 
    //生成bean,注入到IOC容器
	private void registerFeignClient(BeanDefinitionRegistry registry,
			AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
		// feignclient类名称
		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);
		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 = name + "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 });
		//注册到ioc
		BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
	}
}

@FeignClient 类,注入找不到类

原因:

@FeignClinet 和 @EnableFeignClients 不是同一个包。

可能因为springboot和springcloud的版本不一致造成的。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: @FeignClient注入找不到异常如何解决

本文链接: https://lsjlt.com/news/129029.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • @FeignClient注入找不到异常如何解决
    前言 Springcloud中的服务间调用是通过Feign进行调用的,在调用方服务中,我们需要定义一些带有@FeignClient注解的接口类。并且在启动类上加上@EnableFei...
    99+
    2024-04-02
  • java中dubbo注入找不到bean怎么解决
    在Java中使用Dubbo注入找不到Bean的问题可能是由以下几个原因引起的: 未正确配置Dubbo的扫描路径。在Dubbo的配...
    99+
    2023-10-26
    java
  • 如何解决FeignClient发送post请求异常的问题
    本篇内容介绍了“如何解决FeignClient发送post请求异常的问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!FeignClient...
    99+
    2023-06-20
  • 通过Feign进行调用@FeignClient 找不到的解决方案
    目录Feign进行调用@FeignClient 找不到通过Feign 进行调用Feign通过服务名调用服务,找不到服务报错环境报错时,注册中心的情况报错情况Feign进行调用@Fei...
    99+
    2024-04-02
  • python线程捕获不到异常如何解决
    Python线程捕获不到异常的原因是因为线程中的异常默认是不会被抛出到主线程的。 解决这个问题,可以使用try/except语句在线...
    99+
    2023-10-27
    python
  • eclipse找不到tomcat如何解决
    如果Eclipse找不到Tomcat服务器,你可以尝试以下解决方法:1. 确保你已经正确安装了Tomcat服务器,并且知道Tomca...
    99+
    2023-09-26
    eclipse tomcat
  • windows找不到regsvr32jscript.dll如何解决
    如果Windows找不到"regsvr32 jscript.dll"文件,可以尝试以下方法来解决问题:1. 检查文件路径:确保“js...
    99+
    2023-09-29
    Windows
  • win11找不到gpedit.msc如何解决
    Windows 11 Home 版本没有内置 gpedit.msc (组策略编辑器) 工具。但你可以尝试以下方法来解决这个问题:1....
    99+
    2023-09-02
    win11
  • idea找不到WebApplication如何解决
    如果你找不到Web应用的创意,可以尝试以下方法来解决:1. 寻找灵感源:浏览网络上的各种网站、应用和论坛,以获得他人的创意和思路。观...
    99+
    2023-09-21
    idea
  • pycharm找不到pygame如何解决
    如果您安装了Pygame但PyCharm无法找到该库,可以尝试以下解决方法:1. 确认已经正确安装Pygame库。可以在命令行中运行...
    99+
    2023-09-13
    pycharm pygame
  • windows gpedit.msc找不到如何解决
    这篇文章主要介绍了windows gpedit.msc找不到如何解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇windows gpedit.msc找不到如何解决文章都会有所收获,下面我们一起来看看吧。解决方...
    99+
    2023-07-01
  • win10找不到gpedit如何解决
    这篇“win10找不到gpedit如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“win10找不到gpedit如何解决...
    99+
    2023-07-05
  • win10找不到gpedit.msc如何解决
    本文小编为大家详细介绍“win10找不到gpedit.msc如何解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“win10找不到gpedit.msc如何解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。win...
    99+
    2023-07-01
  • Win10找不到msvcr100dll如何解决
    要解决Win10找不到msvcr100dll的问题,可以尝试以下方法:1. 重新安装Microsoft Visual C++ Red...
    99+
    2023-10-20
    Win10
  • linux找不到lib如何解决
    本篇内容介绍了“linux找不到lib如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2023-02-28
    linux lib
  • pecl php找不到如何解决
    本篇内容主要讲解“pecl php找不到如何解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“pecl php找不到如何解决”吧!pecl php找不到的解决办法:1、打开命令窗口;2、检查通过...
    99+
    2023-07-04
  • thinkphp5找不到类如何解决
    这篇文章主要介绍“thinkphp5找不到类如何解决”,在日常操作中,相信很多人在thinkphp5找不到类如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”thinkphp5找不到类如何解决”的疑惑有所...
    99+
    2023-07-06
  • cmd中输入java找不到文件如何解决
    今天小编给大家分享一下cmd中输入java找不到文件如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。解决方法:方法一、...
    99+
    2023-07-01
  • win10加入域找不到网络路径如何解决
    要解决Windows 10加入域后找不到网络路径的问题,你可以尝试以下几个解决方法:1. 检查DNS设置:确保计算机的DNS设置正确...
    99+
    2023-09-12
    win10
  • pycharm找不到解释器如何解决
    当PyCharm找不到解释器时,可以尝试以下解决方法:1. 检查Python是否已正确安装:确保已在计算机上正确安装了Python,...
    99+
    2023-09-25
    pycharm
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作