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();
}
}
任何一个选项都应该有效。
我开发了一个简单的 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();
}
}
任何一个选项都应该有效。