构造函数中的第0个参数需要一个类型为'java.lang.String'的bean,但找不到该bean。

77

我正在使用Spring Boot 2.X应用程序开发Spring Batch,实际上这是我从Git中检出的现有代码。当我运行该应用程序时,它会因为以下错误而失败,但其他人运行同样的代码却没有问题。

s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inputItemReader' defined in file [C:\Users\XYZ\git\main\batch\CBatchProcessing\target\classes\com\main\batchprocessing\batch\reader\InputItemReader.class]: Unsatisfied dependency expressed through **constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations**: {}


Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-10-16 23:23:37.411 ERROR 2384 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

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

Description:

**Parameter 0 of constructor in com.main.batchprocessing.batch.reader.InputItemReader required a bean of type 'java.lang.String' that could not be found.**


Action:

Consider defining a bean of type 'java.lang.String' in your configuration.

我已检查以下内容

  1. 所有的Spring组件都正确地用 @Component,@Service,@Controller,@Repository等进行了注释...
  2. @ComponentScan和@EnableAutoConfiguration也提供了。
  3. 尝试在声明中使用“java.lang.String”。

代码:

    import java.util.Map;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.batch.core.ExitStatus;
    import org.springframework.batch.core.StepExecution;
    import org.springframework.batch.core.StepExecutionListener;
    import org.springframework.batch.item.file.FlatFileItemReader;
    import org.springframework.batch.item.file.mapping.JsonLineMapper;
    import 
    org.springframework.batch.item.file.separator.JsonRecordSeparatorPolicy;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.core.io.FileSystemResource;
    import org.springframework.stereotype.Component;

    @Component
    public class InputItemReader extends  FlatFileItemReader<Map<String, 
     Object>> implements StepExecutionListener {

    @Autowired
    private InputFileHeaderValidator inputFileHeaderValidator; 

    @Autowired
    private FileAuditService fileAuditService;

    private final Logger log = 
    LoggerFactory.getLogger(InputItemReader.class);

    private java.lang.String inputFilePath;

    public InputItemReader(String inputFilePath) {
        setLineMapper(new JsonLineMapper());
        setRecordSeparatorPolicy(new JsonRecordSeparatorPolicy());
        setResource(new FileSystemResource(inputFilePath));
        this.inputFilePath = inputFilePath;
    }
   }

1
@joseph:感谢提供这些链接,但我已经尝试过了。我会编写代码片段。 - Ganesh
1
请阅读在什么情况下可以在我的问题中添加“紧急”或其他类似短语,以便获得更快的答案?——摘要是这不是与志愿者交流的理想方式,可能会适得其反。请勿在您的问题中添加此内容。 - halfer
使用 Lombok,我们可以使用 @NoArgsConstructor 注解。 - vkstream
这可能很有趣,但请确保你的“spring stereotypes”导入是来自Spring而不是其他包!编码愉快。 - Marco-Polo
在我的情况下,问题出在包结构上。ComponentScan 没有找到其他类。 - JavAlex
显示剩余3条评论
32个回答

58

由于您没有提供公共默认构造函数并且添加了自己的非默认构造函数,因此实例化将失败。我建议将输入文件路径定义为属性,例如@Value("${inputFilePath}")。 如果您需要进一步初始化您的bean,请定义一个无返回值的方法并用@PostConstruct进行注释,并在其中进行初始化。


3
是的,这就是答案。在application.properties文件中缺少了inputFilePath变量。感谢@v_schoener。 - Ganesh
1
顺便说一下,从Spring Boot 2.2.x开始,将支持不可变配置,并因此支持属性的构造函数注入。https://github.com/spring-projects/spring-boot/commit/49412173238e622b30c15d6f53132056bf4feb4f?short_path=3034c85#diff-3034c859fdf54b18876462585532bd82,https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2.0-M4-Release-Notes#configuration-property-constructor-parameter-binding,https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2.0-M2-Release-Notes#immutable-configurationproperties-binding - bric3
谢谢您,只需要提供一个默认构造函数就可以解决这个问题。 - Ornelio Chauque

53

在您的类中添加一个公共默认构造函数。例如:

public User() {
}

1
谢谢你分享这个。这帮助我解决了我的项目中的问题。我有点困惑。我的许多服务类没有公共构造函数,即使如此,我仍然能够使用自定义构造函数创建bean。但是我开始在一个服务类中遇到问题,通过提供默认构造函数来解决了这个问题。我从配置类中创建bean,其中参数值从属性文件中获取。 - learner
2
如果您正在使用Lombok,可以在类顶部添加注释(@NoArgsConstructor)。 - vkstream

19

请确保您正在使用 spring-boot-starter-data-jpa。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

3
尽可能提供更多的上下文信息总是有益的。例如,在maven依赖项中没有指定版本,您可以详细介绍一下spring-boot bom,并说明如果未使用bom,则可能需要指定版本。这只是一个例子。如果可能的话,尽量提供至少一些上下文信息总是有好处的。请参见https://stackoverflow.com/help/how-to-answer,特别是在“回答问题”子标题下。 - Nigel Savage

13

我使用lombok的@AllArgsConstructor注解导致了这个问题。我的代码如下:

@Service
@AllArgsConstructor
public class SampleService {

    @Value("${search.page.size}")
    private Integer pageSize;

    private final SampleRepository sampleRepository;

然后我删除了@AllArgsConstructor注解,并添加了@RequiredArgsConstructor注解。问题得到了解决。

@Service
@RequiredArgsConstructor
public class SampleService {

    @Value("${search.page.size}")
    private Integer pageSize;

    private final BatchRepository batchRepository;

这只是一种替代的方法。而不是删除 (@AllArgsConstructor),你也可以添加 (@NoArgsConstructor) 来解决这个问题。 - undefined

11
您定义了如下内容:

您定义了类似于以下内容:

@Component
public class InputItemReader{

   public InputItemReader(String input){
     ...
   }
}

您的类名称表明您的对象不是一个Bean,而只是一个简单的对象。您应该尝试以经典方式使用它:
new InputItemReader(myString);

或者有一个静态方法来处理输入的字符串。

解释:Spring IoC容器将尝试像这样实例化一个新的InputItemReader对象:

new InputItemReader( -- WHAT TO PUT HERE? --) 

如果你不告诉它你期望的和输入字符串,它将无法调用你的构造函数而失败。

更新: 你可以通过删除@Component注解并像这样在配置中定义bean来解决问题:

@Bean
public InputItemReader inputItemReader(InputFileHeaderValidator inputFileHeaderValidator, FileAuditService fileAuditService){
    InputItemReader inputItemReader = new InputItemReader("--HERE SHOULD BE ACTUAL PATH---");
    // set the required service, a cleaner approach would be to send them via constructor
    inputItemReader.setFilteAuditService(fileAuditService);
    inputItemReader.setInputFileHeaderValidator(inputFileHeaderValidator);
    return inputItemReader;
}

我理解你的意思,但是同样的代码在别人那里可以运行,在我的电脑上却不能运行。我真的不明白为什么会这样? 我已经添加了代码,请你帮忙检查一下。 - Ganesh
你应该如何接收 inputFilePath?你在运行之前就知道这个值吗? - Adina Rolea

5

我也遇到了同样的问题,对我来说以下解决方案完美地起作用:

我已经通过导入 import lombok.AllArgsConstructor 将我的类注释为 @AllArgsConstructor

我只是移除了这个注解,代码开始正常工作。


5

我也遇到了同样的错误,但是这个错误是由于Feign Client引起的。如果你在使用Feign客户端时遇到了这个错误,你必须在你的主类上添加@EnableFeignClients

@SpringCloudApplication
@EnableFeignClients
public class Application {
...
}

3
我也遇到了同样的错误:
***************************
APPLICATION FAILED TO START
***************************

Description:

Field repository in com.example.controller.CampaignController required a bean of type 'com.example.data.CustomerRepository' that could not be found.


Action:

Consider defining a bean of type 'com.example.data.CustomerRepository' in your configuration.de here

我通过在主类中添加@EnableMongoRepositories注解解决了这个问题:

@SpringBootApplication
@EnableMongoRepositories(basePackageClasses = CustomerRepository.class)
public class CampaignAPI {

    public static void main(String[] args) {
        SpringApplication.run(CampaignAPI.class, args);
    }
}

很好的发现!这解决了我的问题。不过,是否最好像这样添加所有存储库?basePackageClasses = Foo1Repository.class,Foo2Repository.class... - Zap

2
在我的情况下,问题是一个多余的@Autowired,我最初使用@Autowired添加了一个依赖项,最终注释掉了它,但是我忘记了注释掉这个注解,因此被认为是某种setter的方法就在@Autowired旁边。
去掉多余的注解后,它正常工作了。

2

在我的情况下,我错过了@Service注释,所以一旦我放置它就可以工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接