복붙노트

[SPRING] Autowired는 Custom Constraint validator에서 Null 값을줍니다.

SPRING

Autowired는 Custom Constraint validator에서 Null 값을줍니다.

저는 완전히 봄에 익숙하지 않습니다. 그래서 저는 질문 된 문제에 대해 몇 가지 대답을 들여다 보았습니다. 링크는 다음과 같습니다.

Spring 3.1 사용자 정의 제약 조건 유효성 검사기에서 자동 와이어 링이 작동하지 않습니다.

유효성 검사기에 서비스 자동 연결

사용자 정의 제약 검사기에서 Autowired Repository가 Null입니다.

개체 검증을 위해 Hibernate Validator를 사용하고자하는 Spring 프로젝트가 있습니다. 내가 온라인과 몇 포럼을 읽은 것을 토대로 다음과 같이 유효성 검사기를 주입하려고했습니다.

@Bean
  public Validator validator() {
    return new LocalValidatorFactoryBean().getValidator();
  }

하지만 어디에서든지 내가 사용하고 있었다.

@Autowired
Validator validator;

Hibernate의 유효성 검사기 대신 Spring의 유효성 검사 구현을 사용하고있었습니다. 나는 정확하게 Hibernate validator를 삽입하는 방법을 알아낼 수 없었고 간단하게 다른 클래스에 걸쳐 Autowire를 사용하여 싼 트릭을 사용했다. 이제 Java Config는 다음과 같이 보입니다.

@Bean
      public Validator validator() {
        // ValidatorImpl is Hibernate's implementation of the Validator
        return new ValidatorImpl();
      }

(누군가가 실제로이 Hacky 방식으로 Hibernate Validator를 얻는 것을 피하는 방법에 대해 올바른 방향으로 나를 가리킬 수 있다면 정말 고맙겠습니다.)

그러나 여기에 주요 문제를 제기 할 수 있습니다.

다음은 사용자 정의 유효성 검사 정의입니다.

@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER } )
@Retention(RUNTIME)
@Constraint(validatedBy = EmployeeValidator.class)
@Documented
public @interface EmployeeValidation {
String message() default "{constraints.employeeConstraints}";
public abstract Class<?>[] groups() default {};
public abstract Class<? extends Payload>[] payload() default {};
}

내 사용자 정의 검사기

public class EmployeeValidator implements ConstraintValidator<EmployeeValidation , Object> {

@Autowired
private EmployeeService employeeService;

@Override
public void initialize(EmployeeValidation constraintAnnotation) {
//do Something
 }

@Override
public boolean isValid(String type, ConstraintValidatorContext context) {
    return false;
}
}

위의 Custom Constraint Validator에서 employeeService를 null로 설정했습니다. Spring이 시작될 때 ConstraintValidator의 모든 구현이 인스턴스화되지는 않지만 ValidatorImpl ()을 추가하면 실제로 수정 될 것이라고 생각합니다. 그러나 그렇지 않았습니다.

이제 나는 정말 해킹 된 해결 방법을 고수하고 있으며 이와 같은 코드를 계속 사용하고 싶지 않습니다. 누군가 내 상황을 도와 줄 수 있습니까?

추신 다음은 Java Config 파일의 가져 오기 항목입니다.

import org.hibernate.validator.HibernateValidator; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.MessageSource; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.PropertySource; 
import org.springframework.context.support.ReloadableResourceBundleMessageSource; 
import org.springframework.core.env.Environment; 
import org.springframework.validation.Validator; 
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; 
import org.springframework.web.servlet.LocaleResolver; 
import org.springframework.web.servlet.ViewResolver; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; 
import org.springframework.web.servlet.i18n.CookieLocaleResolver; 
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; 
import org.springframework.web.servlet.view.InternalResourceViewResolver; 

해결법

  1. ==============================

    1.나는 그 해결책이 누군가를 도울 것이라고 희망한다.

    나는 그 해결책이 누군가를 도울 것이라고 희망한다.

    @Bean
    public Validator validator () {
    
        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
            .configure().constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory))
            .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();
    
        return validator;
    }
    

    SpringConstraintValidatorFactory로 유효성 검사기를 초기화하여 주입이 작동하고 Hibernate.class가되도록 유효성 검사 구현을 제공하는 것은 다음과 같은 방식으로 작동합니다.

    작동 원리 : Hibernate의 ConstraintValidatorFactory는 호출되지 않으면 ConstraintValidators를 초기화하지 않지만, SpringConstraintValidatorFactory는 AutowireCapableBeanFactory에 그것을 부여함으로써 초기화된다.

    편집하다

    @shabyasaschi의 코멘트 중 하나에서 언급했듯이 autowireCapableBeanFactory를 삽입하려면 메소드 서명을 다음과 같이 변경할 수 있습니다.

    Validator validator(final AutowireCapableBeanFactory autowireCapableBeanFactory) {
    

    다음과 같이 설정 파일에 getter와 setter를 추가하십시오 :

    public AutowireCapableBeanFactory getAutowireCapableBeanFactory() {
            return autowireCapableBeanFactory;
    }
    
    public void setAutowireCapableBeanFactory(AutowireCapableBeanFactory autowireCapableBeanFactory) {
            this.autowireCapableBeanFactory = autowireCapableBeanFactory;
    }
    
  2. ==============================

    2.당신의 bean 정의에서

    당신의 bean 정의에서

    @Bean
    public Validator validator() {
        return new LocalValidatorFactoryBean().getValidator();
    }
    

    메소드 정의에서 Validator의 유형은 무엇입니까? Spring의 Validator가 아닌 javax.validation.Validator를 반환하는지 확인해야합니다.

    Spring이 Validator를 부트 스트랩하도록하면 SpringConstraintValidatorFactory를 Hibernate Validator로 전달하여 제약 조건 유효성 검사기 내에서 종속성 삽입을 가능하게합니다.

  3. ==============================

    3.이 문제는 다음 두 가지 방법으로 해결할 수 있습니다.

    이 문제는 다음 두 가지 방법으로 해결할 수 있습니다.

    나는 전에도 같은 문제를 겪었고 마침내 나는 많은 문제를 피하면서 두 번째 옵션을 사용하기로 결정했다.

    당신이 가리키는대로 유효성 검사기에 하나의 initialize 메소드를 정의해야하며 ServiceUtils를 사용하여 필요한 서비스 빈을 얻을 수 있습니다.

    @Autowired
    private EmployeeService employeeService;
    
    @Override
    public void initialize(EmployeeValidation constraintAnnotation) {
      //Use an utility service to get Spring beans
      employeeService = ServiceUtils.getEmployeeService();
    }
    

    ServiceUtils는 정적 메소드에서 사용되는 자체에 대한 정적 참조가있는 일반적인 스프링 빈입니다.

    @Component
    public class ServiceUtils {
      private static ServiceUtils instance;
    
      @Autowired
      private EmployeeService employeeService;
    
      /* Post constructor */
    
      @PostConstruct
      public void fillInstance() {
        instance = this;
      }
    
      /*static methods */
    
      public static EmployeeService getEmployeeService) {
        return instance.employeeService;
      }
    }
    

    그래서 당신은 필요한 서비스를 주입하기 위해 Spring을 사용하지만 보통의 방법으로는 사용하지 않습니다. 희망이 도움이됩니다.

  4. ==============================

    4.그게 전부 나를 위해 일했다. 지금 검색하는 사람들에게

    그게 전부 나를 위해 일했다. 지금 검색하는 사람들에게

    public class EmployeeValidator implements ConstraintValidator<EmployeeValidation , Object> {
    
    
        private EmployeeService employeeService;
    
        public EmployeeValidator(EmployeeService employeeService){
            this.employeeService = employeeService;
        }
    
        ...
    }
    
  5. ==============================

    5.

    private XXXService xxxService = SpringContextHolder.getBean(XXXService.class);
    
  6. from https://stackoverflow.com/questions/37958145/autowired-gives-null-value-in-custom-constraint-validator by cc-by-sa and MIT license