【问题标题】:The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true)注入点有以下注解: - @org.springframework.beans.factory.annotation.Autowired(required=true)
【发布时间】:2020-05-16 11:42:20
【问题描述】:

我是 Spring Boot 新手,在编写文件上传 API 时遇到以下错误:

Error:Description:
Field fileStorageService in com.primesolutions.fileupload.controller.FileController required a bean of type 'com.primesolutions.fileupload.service.FileStorageService' 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 'com.primesolutions.fileupload.service.FileStorageService' in your configuration.*

控制器类:

public class FileController 
{
    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private FileStorageService fileStorageService;

    @PostMapping("/uploadFile")
    public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) {
        String fileName = fileStorageService.storeFile(file);

        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/downloadFile/")
                .path(fileName)
                .toUriString();

        return new UploadFileResponse(fileName, fileDownloadUri,
                file.getContentType(), file.getSize());
    }

    @PostMapping("/uploadMultipleFiles")
    public List<UploadFileResponse> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
        return Arrays.asList(files)
                .stream()
                .map(file -> uploadFile(file))
                .collect(Collectors.toList());
    }
}

服务类:

private final Path fileStorageLocation;


    @Autowired
    public FileStorageService(FileStorageProperties fileStorageProperties) {
        this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
                .toAbsolutePath().normalize();

        try {
            Files.createDirectories(this.fileStorageLocation);
        } catch (Exception ex) {
            throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
        }
    }

    public String storeFile(MultipartFile file) {
        // Normalize file name
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());

        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
            }

            // Copy file to the target location (Replacing existing file with the same name)
            Path targetLocation = this.fileStorageLocation.resolve(fileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            return fileName;
        } catch (IOException ex) {
            throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }

配置类:

@ConfigurationProperties(prefix = "file")
public class FileStorageProperties {

    private String uploadDir;

    public String getUploadDir()
    {
        return uploadDir;
    }

    public void setUploadDir(String uploadDir) {
        this.uploadDir = uploadDir;
    }
}

主要:

@SpringBootApplication
@EnableConfigurationProperties({
        FileStorageProperties.class
})
public class FileApplication {
    public static void main(String[] args) {
        SpringApplication.run(FileApplication.class, args);
    }
}

属性文件

## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB

## File Storage Properties
# All files uploaded through the REST API will be stored in this directory
file.upload-dir=C:/Projects/SpringBootProject/Primesolutions/PrimeSolutions/FileUpload

我正在尝试读取文件上传属性并将其传递给控制器​​类。

【问题讨论】:

  • 你的FileStorageService 类是用@Service@Component 注释的吗?从您包含的代码中不清楚。
  • No jordan 它是用@Autowired 注释的
  • 你的构造函数用@Autowired注解,但是为了让Spring能够接受一个类并将其自动装配到其他类中,整个类需要用@Component注解,或者其中之一实现相同接口的其他注解(例如@Service@Controller)。这让 Spring 知道这个类应该由 Spring 管理。如果您使用@Service 在顶层(就在public class FileStorageService 上方)注释您的服务,那应该可以解决您的问题。

标签: java spring-boot


【解决方案1】:

该错误似乎表明 Spring 不知道任何 com.primesolutions.fileupload.service.FileStorageService 类型的 bean。

正如评论中所说,确保你的类FileStorageService@Service@Component注释:

@Service
public class FileStorageService {
...
}

还要确保该类位于您的类FileApplication 的子包中。例如,如果您的 FileApplication 类位于包 com.my.package 中,请确保您的 FileStorageService 位于包 com.my.package.**(相同的包或任何子包)中。

顺便提几点改进代码的注意事项:

  • 当你的类只有一个非默认构造函数时,在构造函数上使用@Autowired是可选的。

  • 不要在构造函数中放置太多代码。请改用@PostConstruct 注释。


    @Service
    public class FileStorageService {
        private FileStorageProperties props;
        // @Autowired is optional in this case
        public FileStorageService (FileStorageProperties fileStorageProperties) {
            this.props = fileStorageProperties;
            this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
                    .toAbsolutePath().normalize();
        }

        @PostConstruct
        public void init() {
            try {
                Files.createDirectories(this.fileStorageLocation);
            } catch (Exception ex) {
                throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
            }
        }
    }

  • 最好避免在字段上使用@Autowired。请改用构造函数。它更适合您的测试,并且更易于维护:
public class FileController {
    private FileStorageService service;

    public FileController(FileStorageService service) {
        this.service = service;
    }
}

【讨论】:

  • 这里有个小问题。假设提到的 FileStorage 类继承自一个接口。其中哪一个要注解为Service?就我而言,我对两者都进行了注释,似乎没有问题,但如果知道要标记哪一个,那就太好了。
  • 查看此链接:stackoverflow.com/questions/16351780/…。最好注释实现类而不是接口
  • 对我来说关键是类在包中的位置,谢谢!
【解决方案2】:

当@Autowired 不起作用时

@Autowired 可能不起作用的原因有多种。

当一个新实例不是由 Spring 而是通过例如手动调用构造函数来创建时,该类的实例将不会在 Spring 上下文中注册,因此不能用于依赖注入。此外,当您在创建新实例的类中使用 @Autowired 时,它不会知道 Spring 上下文,因此很可能这也会失败。 另一个原因可能是您要在其中使用@Autowired 的类没有被ComponentScan 拾取。这基本上有两个原因。

  1. 该包位于ComponentScan 搜索路径之外。移动 打包到扫描的位置或将ComponentScan 配置为 解决这个问题。

  2. 您要在其中使用@Autowired 的类没有 弹簧注解。将以下注释之一添加到类: @Component, @Repository, @Service, @Controller, @Configuration。他们有不同的行为,所以请谨慎选择! 在此处阅读更多内容。

我解决了这个问题:

@ComponentScan({ "com.yourpkg.*" })

确保@ComponentScan 涵盖所有包含注释的类:@Component@Repository@Service@Controller@Configuration

参考:https://technology.amis.nl/2018/02/22/java-how-to-fix-spring-autowired-annotation-not-working-issues/

【讨论】:

    【解决方案3】:

    确保对类有相应的注释。当我为接口和实现的服务类添加 @Service 注释时,同样的问题也解决了

    【讨论】:

      【解决方案4】:

      尝试使用@SpringBootApplication 删除 (exclude = {DataSourceAutoConfiguration.class }) 参数:

      之前:

      @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })

      公共类 SpringBootMain { ...

      之后:

      @SpringBootApplication

      公共类 SpringBootMain { ...

      为我工作。

      【讨论】:

        【解决方案5】:

        您必须在您的服务的类 impl 中添加 @Service 注释,解决方案的来源:here

        【讨论】:

          【解决方案6】:

          将要自动装配的类应该用 @Service@Component 标记。此外,如果该类在不同的包中,则需要在主类中添加 @ComponentScan 注释,如下所示。

          @ComponentScan({"com.beta.replyservice", "com.beta.ruleService"})
          @SpringBootApplication
          

          【讨论】:

            【解决方案7】:

            我使用 @Autowired 注释的地方解决了这个问题,只需用这个替换`

            @Autowired(required = false)

            `

            【讨论】:

              猜你喜欢
              • 2021-04-06
              • 2017-02-27
              • 2014-04-28
              • 1970-01-01
              • 2023-02-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多