NoSuchBeanDefinitionException异常

NoSuchBeanDefinitionException

我开发了一个简单的 class,它从 REST api 获取访问令牌。它没有完全实现,但它的想法是将令牌保存在数据库中。我还有一个函数来检查是否有任何可用的令牌,如果没有,它会调用获取新令牌的函数。我还开发了一个单元测试来检查我是否获得了令牌。

我在 运行 我的测试时遇到了一个问题,一个 NoSuchBeanDefinitionException 问题。我不知道我做错了什么。我对 Spring 引导还是很陌生,所以感谢所有帮助。 下面是我的测试代码和与 REST 端点通信的 class。

TokenIntegration class:

package com.foo.receivable.domain.token;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Arrays;

public class TokenIntegration {

    static final String GET_TOKEN_URI = "";

    static final String API_CLIENT_ID = "";
    static final String API_CLIENT_SECRET = "";
    static final String API_AUDIENCE = "";
    static final String API_GRANT_TYPE = "";

    @Autowired
    private RestTemplate restTemplate;
    private TokenRepository repository;

    private Token API_RetrieveToken(){
        Token t = new Token();
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
            headers.set("client_id", API_CLIENT_ID);
            headers.set("client_secrect", API_CLIENT_SECRET);
            headers.set("audience", API_AUDIENCE);
            headers.set("grant_type", API_GRANT_TYPE);

            HttpEntity<String> entity = new HttpEntity<>(headers);
            ResponseEntity<String> response = restTemplate.exchange(GET_TOKEN_URI, HttpMethod.POST, entity, String.class);
//not implemented yet

        }catch(Exception e){
            e.printStackTrace();
        }
        return t;
    }

    public Token GetAccessToken(){
        Token token;
        try {
            token = repository.findByExpired(LocalDateTime.now());
            if(token == null){
                token = API_RetrieveToken();
            }
        }
        catch (Exception e){
            token = null;
            e.printStackTrace();
        }
        return token;
    }
}

TokenIntegrationTestclass:

package com.foo.receivable.domain.token;

import com.foo.receivable.infra.AbstractTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class TokenIntegrationTest  extends AbstractTest {

@Autowired
private TokenIntegration integration;

@Test
void ShouldReturnTokenObject(){
    final Token token = integration.GetAccessToken();
    if(token == null){
        //not implemented yet
    }
    assertEquals(Token.class, token.getClass());
}
}

还有我的异常跟踪:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.foo.receivable.domain.token.TokenIntegrationTest': Unsatisfied dependency expressed through field 'integration'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.foo.receivable.domain.token.TokenIntegration' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

编辑: 问题是缺少 @Component 注释,因此 spring 无法将我的 TokenIntegration class 识别为 bean。在我更改它之后,我又遇到了一个关于拥有 RestTemplate bean 的错误。有什么帮助吗?

***************************
APPLICATION FAILED TO START
***************************

Description:

Field restTemplate in com.foo.receivable.domain.token.TokenIntegration required a bean of type 'org.springframework.web.client.RestTemplate' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration.

2021-05-10 11:44:50.801 ERROR 19916 --- [           main] o.s.test.context.TestContextManager      : Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@70ab2d48] to prepare test instance [com.foo.receivable.domain.token.TokenIntegrationTest@22a9170c]

java.lang.IllegalStateException: Failed to load ApplicationContext

可能是因为 TokenIntegration 没有注解 Spring 表明它是一个 bean,或者它在一个未扫描的包中。

在您的代码段中,TokenIntegration class 被命名为 TagIntegration,至少这可能是原因。 通过更改名称,我成功地 运行 测试(至少 bean 定义的问题消失了)。 下面是 Spring 如何搜索 beans 的一个很好的答案:.

您将 TokenIntegration 标记为 @Autowired,因此您需要告诉 Spring 它应该管理您的 TokenIntegration bean:

@Component
public class TokenIntegration

这会让 Spring 知道创建其中一个 bean 并将其放入应用程序上下文中,这样 Spring 就可以为您的 [=11] 提供一个 bean =] 字段.

换句话说:

如果 bean 不在 Spring 的应用程序上下文中,则它不能被 Spring 自动装配。据Spring所知,它不存在。

回答您的编辑:

您需要为 spring 定义 class 才能注入。您可以在 xml 或注释中执行此操作。 ps:

@Service
public class TokenIntegration {
}

A class 通过以下方式被识别为 Spring 中的 Bean:

1> 使用@Component 或专门的@Service 等注释。这通常在 class 中实现,它应该是一个 bean。 2> 它也可以在 public 方法上使用 @Bean 注释实现,并在使用 @Configuration 注释注释的 class 中实现。

对于您的情况,您可以使用以下选项:

选项 A>

@Component
public class TokenIntegration {
......
....

选项 B>

@Configuration
public class AppConfig {

@Bean
public TokenIntegration tokenIntegration() {
   return new TokenIntegration();
}
}

任何一个选项都应该有效。