Не может связывать компоненты при загрузке Spring. Уровень служб и контроллеров REST

#java #spring #spring-boot

#java #весна #spring-boot

Вопрос:

Добрый вечер! Я хочу получить список объектов через REST. Ниже приведен мой код.

Репозиторий

 public interface CustomerRepository extends JpaRepository<Customer, Long> {}
  

Интерфейс службы

 public interface CustomerService {
    Page<CustomerRsDto> getAll(Pageable pageable);
}
  

Реализация интерфейса сервиса

 @Service
@RequiredArgsConstructor
public class CustomerServiceImpl implements CustomerService {
    private final CustomerService customerService;
    
    @Override
    @Transactional
    public Page<CustomerRsDto> getAll(Pageable pageable) {
        Page<CustomerRsDto> rsCustomers = customerService.getAll(pageable);
        return rsCustomers;
    }
}
  

Контроллер REST

 @RestController
@RequiredArgsConstructor
@RequestMapping("/customers")
@Api(tags = "customers", value = "Customres")
public class CustomersController {
    private CustomerService customerService;

    @GetMapping
    @ApiOperation(tags = "customers", value = "Get all")
    public Page<CustomerRsDto> getAll(Pageable pageable) {
        if (isNull(customerService)) {
            System.out.println("Not linked bean?");
        }
        return customerService.getAll(pageable);
    }
}
  

Когда я пытаюсь запустить этот код, я получаю две ошибки от компилятора. Это

 WARN 8928 --- [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerServiceImpl' defined in file [<My Patch>serviceimplCustomerServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'customerServiceImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?
  

и это

 ERROR 8928 --- [main] o.s.b.d.LoggingFailureAnalysisReporter: 

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

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  customerServiceImpl defined in file [<My Patch>serviceimplCustomerServiceImpl.class]
└─────┘

Process finished with exit code 1
  

Я нашел решение в другом похожем вопросе, используя конструктор и аннотацию @Lazy . Ниже приведен измененный код.

Реализация интерфейса сервиса

 @Service
public class CustomerServiceImpl implements CustomerService {
    private final CustomerService customerService;

    public CustomerServiceImpl(@Lazy CustomerService customerService) {
        super();
        this.customerService = customerService;
    }

    @Override
    @Transactional
    public Page<CustomerRsDto> getAll(Pageable pageable) {
        Page<CustomerRsDto> rsCustomers = customerService.getAll(pageable);
        return rsCustomers;
    }
}
  

И я получаю новую ошибку.

 2020-11-11 17:59:29.826  INFO 1236 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 7 ms
Not linked bean?
2020-11-11 17:59:30.308 ERROR 1236 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null
    at <My Package>.rest.CustomersController.getAll(CustomersController.java:31) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.10.RELEASE.jar:5.2.10.RELEASE]
  

В чем моя ошибка? Спасибо всем, кто ответил на этот пост!

Upd 1:

Реализация интерфейса сервиса

 @Service
@RequiredArgsConstructor
public class CustomerServiceImpl implements CustomerService {
    private final CustomerRepository customerRepository;
    private final CustomerMapper customerMapper;

    @Override
    @Transactional
    public Page<CustomerRsDto> getAll(Pageable pageable) {
        List<Customer> dbCustomers = customerRepository.findAll();
        List<CustomerRsDto> listCustomers = null;

        dbCustomers.forEach(dbCustomer -> {
            listCustomers.add(customerMapper.toRsDto(dbCustomer));
        });

        Page<CustomerRsDto> rsCustomers = new PageImpl<CustomerRsDto>(listCustomers);

        return rsCustomers;
    }
}
  

Ответ №1:

Наличие CustomerServiceImpl зависимости от CustomerService не кажется правильным. Из общих фрагментов кода похоже CustomerServiceImpl , что это единственная реализация CustomerService , поэтому зависимость от компонента типа CustomerService неверна. Похоже, это причина, по которой он сначала жалуется на циклическую зависимость в журналах.

Похоже, намерение,

  1. чтобы иметь зависимость от CustomerRepository
  2. для создания CustomerRsDto экземпляров CustomerServiceImpl после извлечения Customer экземпляров из CustomerRepository

Они CustomerServiceImpl должны измениться, чтобы иметь зависимость CustomerRepository .

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

1. Я наивно предположил, что GetAll может вызывать findAll благодаря магии Spring Boot . Теперь я возвращаю, вероятно, правильный объект. Но это не помогает. До этого я также просто пытался вернуть null в GetAll.

2. Изменения в коде отмечены в заголовке вопроса.

3. @HtmlMan, я предлагаю пересмотреть код. Обновленный код использует listCustomers то, что назначено null . Обновленный код должен быть запущен NullPointerException сейчас при попытке добавить Customer . Код также выполняет a findAll для CustomerRepository , и это может быть проблематично, если имеется большое количество клиентов, поскольку он будет пытаться извлечь все в памяти. Spring предоставляет хорошую документацию, поэтому обращайтесь spring.io/learn и docs.spring.io/spring-data/jpa/docs/2.2.11.RELEASE/reference /.