@Autowired класс из службы не может быть преобразован в тип в классе контроллера

#java #spring-boot

#java #spring-boot

Вопрос:

Я очень новичок в spring boot и всю жизнь не могу понять, почему мой класс @Autowired FarmService из service не может быть преобразован в тип в классе контроллера. Мой класс приложения находится на уровне пакета выше класса service и controller.

Это иерархия пакетов

FarmApplication.java-код:

 package prac.farm;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

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

}
  

FarmController.java код:

 package prac.farm.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class FarmController {
    
    @Autowired
    private FarmService farmservice;
    
    @RequestMapping(value = "/home", method = RequestMethod.GET)
    public String display() {
        return farmservice.getOwner();
    }

}
  

FarmService.java код:

 package prac.farm.service;

import org.springframework.stereotype.Service;

@Service
public class FarmService {
    private String owner;
    private String location;
    private int yearsOwned;
    
    public FarmService() {
        super();
        this.owner = "alale";
        this.location = "Uppsa";
        this.yearsOwned = 2;
    }
    
//  public FarmService(String owner, String location, int yearsOwned) {
//      super();
//      this.owner = owner;
//      this.location = location;
//      this.yearsOwned = yearsOwned;
//  }
    
    public String getOwner() {
        return owner;
    }
    public void setOwner(String owner) {
        this.owner = owner;
    }
    public String getLocation() {
        return location;
    }
    public void setLocation(String location) {
        this.location = location;
    }
    public int getYearsOwned() {
        return yearsOwned;
    }
    public void setYearsOwned(int yearsOwned) {
        this.yearsOwned = yearsOwned;
    }


}
  

Комментарии:

1. Я не вижу никакого импорта для службы?

2. какую ошибку вы получаете в FarmController?

3. Почему вы ожидали, что FarmController класс сможет использовать FarmService без import инструкции? Класс service находится в другом пакете .

4. Не является ли @Autowire жизнеспособной заменой импорта в spring boot? У меня неправильное представление?

Ответ №1:

Прежде всего, @ComponentScan является избыточным, поскольку @SpringBootApplication уже включает эту аннотацию. Во-вторых, вы, похоже, не импортируете класс FarmService в свой контроллер.

Комментарии:

1. У меня неправильное представление о @Autowired? У меня сложилось впечатление, что @Autowired служит той же цели, что и import для Spring boot. Спасибо за ваш ответ, кстати.

2. Да, вы делаете. @Autowired вводит экземпляр класса из контекста spring в аннотированное поле.

Ответ №2:

Итак, я думаю, что ваша путаница возникает из-за разрыва между тем, что вы слышали о Spring как о платформе внедрения зависимостей, и вашим компилятором, выдающим вам эту ошибку.

Ключевым моментом Spring является то, что он действует только во время выполнения. Если вы действительно думаете о том, что говорит вам компилятор, это имеет большой смысл. У вас есть этот класс с именем FarmService, который вы не импортировали, поэтому с точки зрения компилятора FarmController ничего не знает о том, что такое FarmService и какие методы у него есть.

Итак, если вам нужно поместить оператор import, разве это не просто добавляет его как зависимость и сводит на нет весь смысл использования spring в первую очередь, когда мы пытаемся ослабить связь? Решением является интерфейс.

Создайте вызываемый интерфейс FarmService и используйте его в своем классе контроллера. Затем переименуйте свой текущий класс FarmServiceImpl , который реализует этот интерфейс. Вам не нужно импортировать реализацию. При запуске Spring он автоматически подключит реализацию. Таким образом, у вас нет явной зависимости от реализации в вашем коде, но он все равно будет использоваться во время выполнения.