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

#spring-boot #hibernate-validator #cglib #nhibernate-validator

#пружинный ботинок #спящий режим-валидатор #cglib #nhibernate-валидатор

Вопрос:

Я создал приложение spring boot (пользователь spring-boot-starter-parent версии 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");
  }
}
 

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

Ответ №1:

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

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

1. Хорошо, рад, что вы нашли это. Спасибо, что поделились своим решением.

Ответ №2:

Используя предоставленный вами код и создавая фиктивный 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>.m2repository и перестроить с помощью maven.

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

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

1. хорошо, сначала я проверил его независимо от IDE, запустив его с помощью mvn spring-boot: run с тем же эффектом. Затем я создал проект с теми же библиотеками, базовыми материалами и контроллером rest. Оказалось, что все работает нормально, и объекты проверены. Я поместил точку останова внутри метода контроллера и увидел, что «this» — это простой класс, в котором поле автоматически подключено. В то время как в исходном проекте это класс класса $$ EnhancerBySpringCGLIB $$, в котором поля не подключены автоматически. Он также имеет CGLIB$CALLBACK_1.target, ссылающийся на исходный класс

2. он также содержит ссылку на фабрику прокси: org.springframework.aop.framework. ProxyFactory: 0 интерфейсов []; 1 советник [org.springframework.aop.support. DefaultPointcutAdvisor: pointcut [AnnotationMatchingPointcut: org.springframework.aop.support.annotation. Аннотацияclassfilter: организация интерфейса.springframework.validation.annotation. Проверено, сопоставитель методов. TRUE]; Так что это также должно быть результатом проверки. Я не уверен, в чем различия, в исходной конфигурации проекта нет специальных аннотаций

3. хорошо, это была супер глупая ошибка, на которую мне потребовалось несколько часов, чтобы заметить. В исходном проекте методы контроллера были закрытыми, и это вызвало эффект, я не могу удалить свой вопрос сейчас :/