@FeignClient 주입 에서 이상 을 찾 을 수 없습니다.어떻게 해결 해 야 합 니까?
8866 단어 @FeignClient주입이상 하 다
Springcloud 의 서비스 간 호출 은 Feign 을 통 해 호출 됩 니 다.호출 자 서비스 에서 저 희 는@FeignClient 주 해 를 가 진 인터페이스 류 를 정의 해 야 합 니 다.또한 시작 클래스 에@Enable FeignClient 주 해 를 추가 합 니 다.
프로그램 이 시 작 될 때@EnableFeignClient 주해 가 있 는 지 확인 합 니 다.이 주해 가 있 으 면 패키지 스 캔 을 열 고@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
한 차례 조사 한 결과,시작 에 있 는@EnableFeignClient 주 해 를 발 견 했 고,basePackages 패키지 스 캔 경 로 를 지정 하지 않 았 습 니 다.
또한 Client 1 Feign 인 터 페 이 스 는 시작 클래스 와 같은 디 렉 터 리 에 있 지 않 기 때문에 시작 할 때 상기 오 류 를 보고 합 니 다.
나중에@Enable FeignClient 에서 스 캔 패키지 경 로 를 지정 하면 해 결 됩 니 다.
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.aiqinhai.client2.feignclient"})
public class Client2Application {
public static void main(String[] args) {
SpringApplication.run(Client2Application.class, args);
}
}
문 제 는 확실히 해결 되 었 지만,우 리 는 서비스 가 시 작 될 때@EnableFeignClient 가 어떤 일 을 했 는 지 알 아야 합 니 다.@EnableFeignClient
이 주해 의 작용 을 똑똑히 알 고 싶다 면 가장 좋 은 방법 은 주해 의 원본 코드 를 보 는 것 이다.눌 러 서 보 여요.
/**
* @FeignClient
*/
@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 는 FeignClient 레지스터 클래스 입 니 다.들 어가 보 니 패키지 스 캔 의 논 리 는 FeignClient 레지스터 에서 이 루어 진 것 입 니 다.모든'class 파일'을 스 캔 하여@FeignClient 에 표 시 된 인 터 페 이 스 를 걸 러 낸 다음 Bean DefinitionBuilder 를 통 해 FeignClient Factory Bean 대상 을 생 성하 여 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 과@EnableFeignClient 는 같은 가방 이 아 닙 니 다.
springboot 과 springcloud 버 전이 일치 하지 않 아서 그런 가 봐 요.
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Spring의 두 가지 주입 방식(Set 및 구성) 인스턴스 이해의존 주입은 대상 간의 관계에 대한 제어권이 응용 코드에서 외부 용기로 넘어가는 것을 말한다.스프링 프레임워크는 주로 Set 주입과 구조 주입 두 가지 의존 주입 방식을 제공한다. 1:Set 주입은 주입을 받는 클래...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.