Spring找不到自动接线的接口实现

时间:2019-12-10 19:13:29

标签: spring spring-boot dependency-injection spring-ioc

我在这里有一个主要的SpringBootApplication类:

package com.example.springproj;

@SpringBootApplication
public class App {

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

@RestController类在这里:

package com.example.springproj.controller;

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    @Qualifier("RefDataServiceImpl")
    private RefDataService refDataService;

    @GetMapping(path = {"/refdata"}, produces = {"application/json"})
    public ResponseEntity<Configuration> getRefData() {
        // etc
    }
}

控制器自动连接此接口:

package com.example.springproj.service;

public interface RefDataService {

    Configuration getConfiguration(String param);
}

哪些是由此类实现的:

package com.example.springproj.services;
@Service
public class RefDataServiceImpl implements RefDataService {

    @Autowired
    private ConfigRepository config;

    @Value("${ENV}")
    private String environment;

    @Override
    public Configuration getConfiguration(String param) {
        // etc
    }
}

但是当我运行App.java文件时,我得到了

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

Description:

Field refDataService in com.citi.icrm.risk.springproj.controller.RefDataController required a bean of type 'com.citi.icrm.risk.springproj.service.RefDataService' that could not be found.

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


Action:

Consider defining a bean of type 'com.citi.icrm.risk.springproj.service.RefDataService' in your configuration.

我有合理的把握,这种自动装配应该可以工作,而且我不确定如何在Spring Boot应用程序中配置此bean。我在做什么错了?

编辑:我已经尝试过的事情包括:

删除所有@Qualifier批注

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    private RefDataServiceImpl refDataService;

    @GetMapping(path = {"/refdata"}, produces = {"application/json"})
    public ResponseEntity<Configuration> getRefData() {
        System.err.println("testing.");
        return new ResponseEntity<Configuration>(refDataService.getConfiguration("EEMS_USER_DETAIL_URL"), HttpStatus.OK);
    }
}
public class RefDataServiceImpl implements RefDataService {

    @Autowired
    private ConfigRepository config;

    @Value("${ENV}")
    private String environment;

    @Override
    public Configuration getConfiguration(String param) {
        try {
            return config.getConfiguration(param, environment);
        } catch (Exception e) {
            e.printStackTrace();
            throw (RuntimeException) new RuntimeException().initCause(e);
        }
    }
}

更改bean名称以符合约定

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    @Qualifier("refDataServiceImpl")
    private RefDataService refDataService;

    @GetMapping(path = {"/refdata"}, produces = {"application/json"})
    public ResponseEntity<Configuration> getRefData() {
        System.err.println("testing.");
        return new ResponseEntity<Configuration>(refDataService.getConfiguration("EEMS_USER_DETAIL_URL"), HttpStatus.OK);
    }
}
@Service("refDataServiceImpl")
public class RefDataServiceImpl implements RefDataService {

    @Autowired
    private ConfigRepository config;

    @Value("${ENV}")
    private String environment;

    @Override
    public Configuration getConfiguration(String param) {
        try {
            return config.getConfiguration(param, environment);
        } catch (Exception e) {
            e.printStackTrace();
            throw (RuntimeException) new RuntimeException().initCause(e);
        }
    }
}

作为参考,这些文件将落入应用程序的包结构中,如下所示:

com.example.springproj
-> com.example.springproj.controller
--> RefDataController
-> com.example.springproj.services
--> RefDataService
-> com.exampple.springproj.services.impl
---> RefDataServiceImpl

这是文件夹结构,因为有人问过:

enter image description here

4 个答案:

答案 0 :(得分:3)

首先,如果您只有@Qualifier("RefDataServiceImpl")接口的一种实现,则不需要RefDataService。 您只需要

@Autowired
private RefDataService refDataService;

第二,在类名上生成的bean的名称,但以小写字母开头。在您的示例中,bean的名称将类似于refDataServiceImpl。 因此,您可以像下面这样自动接线该豆

@Autowired
@Qualifier("refDataServiceImpl")
private RefDataService refDataService;

第三,您可以指定bean的名称

@Service("youBeanName")
public class RefDataServiceImpl implements RefDataService

,然后通过控制器中的名称自动连接该bean,例如

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    @Qualifier("youBeanName")
    private RefDataService refDataService;

    //....
}

答案 1 :(得分:1)

按如下所示更改@Service类上的RefDataServiceImpl批注:

@Service("RefDataServiceImpl")
public class RefDataServiceImpl implements RefDataService

自动连线服务中的@Qualifier名称与您的spring配置中的bean不匹配。 默认的命名约定是该类的完整路径。 因为这, Spring可能在您的RefDataServiceImpl服务的配置中使用的名称是:“ com.example.springproj.services.RefDataServiceImpl”。

已添加: 此页面可能是不错的阅读:https://www.baeldung.com/spring-qualifier-annotation

尝试两个: 试试这个

@Service
@Qualifier("RefDataServiceImpl")
@Service("RefDataServiceImpl")
public class RefDataServiceImpl implements RefDataService

答案 2 :(得分:0)

我通过将RefDataServiceImplRefDataService放在同一包中解决了这个问题。在此之前,我将其放在主services包的子文件夹中。我仍然确定我应该可以通过实现子文件夹来完成这项工作,但是现在这可以作为解决方案。

答案 3 :(得分:0)

我在尝试使用数据库查询实现类时遇到了同样的问题。将 @Repository 添加到已实现类的顶部解决了我的问题。