#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 он автоматически подключит реализацию. Таким образом, у вас нет явной зависимости от реализации в вашем коде, но он все равно будет использоваться во время выполнения.