Добавление ведения журнала аспектов вызывает исключение создания экземпляра компонента

#java #spring #spring-boot #spring-mvc #spring-aop

#java #весна #весенняя загрузка #spring-mvc #spring-aop

Вопрос:

У меня есть простой сервис, в котором я хочу вести журнал через Spring AOP. Я получаю компонент при его запуске, у меня есть компонент для RestTemplate в контроллере, который уже определен, пожалуйста, предложите, если здесь что-то отсутствует.

Трассировка стека :

 
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demo1Controller': Unsatisfied dependency expressed through field 'restTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restTemplate' defined in class path resource [com/test/demo1/controller/Demo1Controller.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.client.RestTemplate]: Circular reference involving containing bean 'demo1Controller' - consider declaring the factory method as static for independence from its containing instance. Factory method 'restTemplate' threw exception; nested exception is java.lang.NullPointerException

 

Мой класс аспектов DemoHttpAspect.java

 @Aspect
@Component
@Order(1)
public class DemoHttpAspect {

    private final static Logger logger = LoggerFactory.getLogger(DemoHttpAspect.class);

    
    @After("execution(public * com.test.demo1.controller.*.*(..))")
    public void logAfter() throws Throwable {
        System.out.println(SplunkLogImpl.of("Performance Logging via AspectJ, Into DemoAspect"));
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        HttpAspectCore.controllerEvents(request);
        System.out.println(SplunkLogImpl.of("Performance Logging via AspectJ, Out of CoreAspect"));
    }
    
}
 

Мой класс контроллера

 package com.test.demo1.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


@RestController
public class Demo1Controller {

    @Autowired
    RestTemplate restTemplate;
 
    @Bean
    public RestTemplate restTemplate()
    {
        return new RestTemplate();
    }
 
    @RequestMapping("/demo1/name")
    public String getMicroserviceName()
    {
          String micro2Response = restTemplate.postForObject("http://localhost:8084/service/sleuth", null, String.class);
          System.out.println("getMicroserviceName");
        return "Demo"   " : "   micro2Response ;
    }
    
    @GetMapping("/demo1/sleuth")
    public String helloSleuth(@RequestHeader HttpHeaders headers) {
        System.out.println("helloSleuth");
        System.out.println("headers.getClass()" headers.getClass());
        return "success demo1";
    }
}
 

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

1. Вы не должны помещать Bean методы в компоненты. Удалите его (и это также решит вашу проблему).

2. @M.Deinum, если я удалю аннотацию, это даст: Описание: для поля RestTemplate в com.test.demo1.controller.Demo1Controller требуется компонент типа org.springframework.web.client. RestTemplate’ который не удалось найти. Точка внедрения имеет следующие аннотации: — @org.springframework.beans.factory.annotation. Действие с автоматической настройкой (обязательно = true): Рассмотрите возможность определения компонента типа ‘org.springframework.web.client. RestTemplate’ в вашей конфигурации.

3. сэр, если прокомментировал «//@Component» в aspect, и он начал работать, но ведение журнала аспектов не работает, не уверен, нужно ли это для Aspect.

Ответ №1:

Ваш Demo1Controller зависит от RestTemplate, но он также определяет его как облегченный компонент. Итак, у вас есть циклическая зависимость, вам нужен Demo1Controller для создания RestTemplate, но Demo1Controller нуждается в RestTemplate.

У вас есть два решения:

  1. переместите определение @Bean в класс @Configuration
  2. сделайте метод статическим.

В данном случае рекомендуется первое решение.

 @Configuration
public class DepsConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@RestController
public class Demo1Controller {

    @Autowired
    RestTemplate restTemplate;
 
    @RequestMapping("/demo1/name")
    public String getMicroserviceName()
    {
          String micro2Response = restTemplate.postForObject("http://localhost:8084/service/sleuth", null, String.class);
          System.out.println("getMicroserviceName");
        return "Demo"   " : "   micro2Response ;
    }
    
    @GetMapping("/demo1/sleuth")
    public String helloSleuth(@RequestHeader HttpHeaders headers) {
        System.out.println("helloSleuth");
        System.out.println("headers.getClass()" headers.getClass());
        return "success demo1";
    }
}

 

Поскольку вы используете spring boot, я полагаю, вы используете ComponantScanning по умолчанию, что означает, что DepsConfig должен находиться в пакете (или подпакете), в котором определено приложение.

Я предлагаю вам ознакомиться с документацией о том, как IoC работает с spring и как определять компоненты. И как работает автоконфигурация spring boot.

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

1. Использование «@Configuration» приводит к появлению нескольких маркеров в этой строке — Конфигурация не может быть преобразована в тип — аннотация @Configuration запрещена для этого местоположения

2. это должно использоваться в классе

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

4. Я обновил свой ответ, но это действительно базовая весна.

5. На самом деле, даже сообщение об ошибке, опубликованное Вики, уже предлагает то, что ДЖЕЙ более подробно объяснил здесь в качестве одного из возможных решений: «Циклическая ссылка, включающая содержащий компонент’demo1Controller’ — рассмотрите возможность объявления фабричного метода как статического для независимости от содержащего его экземпляра». Иногда это помогает просто прочитать сообщение об ошибке. Что касается «Конфигурация не может быть преобразована в тип» , возможно, просто импортируйте правильный класс. Ваша среда разработки должна помочь вам и предложить ее автоматически.