Проверка весенней загрузки Расширенные компоненты контроллера CGLIB не подключены автоматически

Я создал приложение весенней загрузки (пользователь spring-boot-starter-parent V. 2.2.2.RELEASE) с контроллерами Rest, которые отлично работают, теперь я добавил зависимость:

    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-validation</artifactId> 
    </dependency> 

И добавил @Validated в мой класс контроллера, чтобы все методы в нем были проверены:

@RestController
@Validated 
public class UserController {
  @Autowired
  private UserService userService;

  @PostConstruct
  public void init() {
    System.out.println("test");
  }
}

Теперь методы контроллера при вызове начинают генерировать исключения NullPointerException, потому что userService имеет значение null; Я сделал @PostConstruct в качестве теста. По-видимому, он вызывается для обычного нерасширенного bean-компонента, в котором поля автоматически подключены правильно. Но при вызове контроллера через HTTP этот нерасширенный bean-компонент не вызывается, а является bean-компонентом класса UserController$$EnhancerBySpringCGLIB$$ и имеет неавтоматически связанный userController. Я действительно не знаю, почему это должно быть очень просто, насколько я знаю, не так много настроек. Поэтому я предполагаю, что по какой-то причине Spring не вводит зависимости в расширенные классы CGLIB или просто вводит их в неправильный класс. Когда я удаляю @Validated, все снова работает нормально, но проверки, конечно же, нет.


person maslan    schedule 21.11.2020    source источник


Ответы (2)


Это была самая нелепая ошибка, которую я имел за целую вечность. Я по ошибке установил методы контроллера в своем исходном проекте как частные. Это заставило CGLIB не улучшать их, а вместо этого просто иметь их с исходным кодом. Spring не жаловался и с удовольствием запускал эти методы.

person maslan    schedule 27.11.2020
comment
Хорошо, рад, что вы нашли его. Спасибо, что поделились своим решением. - person geekTechnique; 27.11.2020

Взяв предоставленный вами код и создав фиктивный класс UserService, HTTP-запросы будут нормально работать в других средах.

Чтобы помочь решить возникшую проблему, вам следует создать новый проект, добавив зависимости lombok, starter-web и starter-validation. Создайте следующие классы.

@RestController
@Validated
public class UserController {
    @Autowired
    private UserService userService;

    @PostConstruct
    public void init() {
        System.out.println("test");
    }

    @GetMapping("/test")
    public int test(){
        return userService.getAge();
    }
}

@Data
@Service
public class UserService {
    private int age = 21;
}

Затем проверьте http://localhost:8080/test

Если это не сработает для вас, попробуйте аннулировать кеш и перезапустить IDE. У Intellij есть опция для этого, если вы нажмете File > Invalidate Caches / Restart .... Кроме того, вы можете удалить артефакты (или полное локальное репо) из папки .m2. C:\Users\<username>\.m2\repository и пересоберите с помощью maven.

Если это по-прежнему не решает вашу проблему, обновите свой вопрос, указав более полный воспроизводимый пример вашей проблемы вместе с полным консольным журналом вашей ошибки, и я обновлю свой ответ.

person geekTechnique    schedule 21.11.2020
comment
Хорошо, сначала я проверил это независимо от IDE, запустив его с помощью mvn spring-boot:run с тем же эффектом. Затем я создал проект с теми же библиотеками, базовыми вещами и остальным контроллером. Оказалось все работает нормально и объекты проходят валидацию. Я поместил точку останова внутри метода контроллера и увидел, что это простой класс с автоматически подключаемым полем. Хотя в исходном проекте это класс класса $$EnhancerBySpringCGLIB$$, в котором поля не связаны автоматически. Он также имеет CGLIB$CALLBACK_1.target, ссылающийся на исходный класс. - person maslan; 27.11.2020
comment
он также содержит ссылку на фабрику прокси: org.springframework.aop.framework.ProxyFactory: 0 interfaces []; 1 советник [org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [AnnotationMatchingPointcut: org.springframework.aop.support.annotation.AnnotationClassFilter: interface org.springframework.validation.annotation.Validated, MethodMatcher.TRUE]; Так что это также должно было произойти в результате проверки. Я не уверен, в чем отличия, в исходной конфигурации проекта нет специальных аннотаций. - person maslan; 27.11.2020
comment
хорошо, это была супер глупая ошибка, которую я заметил несколько часов. В исходном проекте методы контроллера были закрытыми, и это вызвало эффект, теперь я не могу удалить свой вопрос:/ - person maslan; 27.11.2020