bean validator를 배우기전에 스프링은 검증을 체계적으로 하기위해 다음과 같은 인터페이스를 제공한다.
public interface Validator {
	boolean supports(Class<?> clazz);
	void validate(Object target, Errors errors);
}
아래와 같이 구현체를 만들었다. 특히 supports 주석을 잘 봐라!
@Component
	public class ItemValidator implements Validator {
	
	@Override
	public boolean supports(Class<?> clazz) {
		return Item.class.isAssignableFrom(clazz);
		// 클래스명.class.isAssignableFrom(clazz)를 쓰는 이유?
		// Item == clazz
		// Item == subItem
		// 그 클래스의 자식까지 인정해줌!
}
	@Override
	public void validate(Object target, Errors errors) {
		Item item = (Item) target;
		
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "itemName",
		"required");
		
		if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice()
			> 1000000) {
			errors.rejectValue("price", "range", new Object[]{1000, 1000000},
			null);
			
		if (item.getQuantity() == null || item.getQuantity() > 10000) {
			errors.rejectValue("quantity", "max", new Object[]{9999}, null);
		}
		
	}
		//특정 필드 예외가 아닌 전체 예외
		if (item.getPrice() != null && item.getQuantity() != null) {
		
			int resultPrice = item.getPrice() * item.getQuantity();
			
		if (resultPrice < 10000) {
			errors.reject("totalPriceMin", new Object[]{10000, resultPrice},
			null);
		}
	}
}
}
위의 코드와 같이 Validator를 구현한 구현체를 아래와 같이 api 호출 시작에 직접 불러줄 수 있지만?~?!~?!
private final ItemValidator itemValidator;
@PostMapping("/add")
public String addItemV5(@ModelAttribute Item item, BindingResult bindingResult,
RedirectAttributes redirectAttributes) {
		// 이거
		itemValidator.validate(item, bindingResult);
		
		if (bindingResult.hasErrors()) {
			log.info("errors={}", bindingResult);
			
			return "validation/v2/addForm";
		}
		
		//성공 로직
		Item savedItem = itemRepository.save(item);
		
		redirectAttributes.addAttribute("itemId", savedItem.getId());
		
		redirectAttributes.addAttribute("status", true);
		
		return "redirect:/validation/v2/items/{itemId}";
	}
이렇게 WebDataBinder 에 검증기를 추가하면 해당 컨트롤러에서는 검증기를 자동으로 적용할 수 있다.
@InitBinder 해당 컨트롤러에만 영향을 준다. 글로벌 설정은 별도로 해야한다.
	@InitBinder
	public void init(WebDataBinder dataBinder) {
	
	log.info("init binder {}", dataBinder);
	
	dataBinder.addValidators(itemValidator);
	
}
위에서 WebDataBinder에 추가한 검증기를 @Validated를 추가하면 해당 controller를 실행할때마다 자동으로 실행해준다!! 얼마나 편해짐~!
@PostMapping("/add")  // 아래 어노테이션
public String addItemV6(@Validated @ModelAttribute Item item, BindingResult
bindingResult, RedirectAttributes redirectAttributes) {
	if (bindingResult.hasErrors()) {
		log.info("errors={}", bindingResult);
		
		return "validation/v2/addForm";
}
		//성공 로직
		Item savedItem = itemRepository.save(item);
		
		redirectAttributes.addAttribute("itemId", savedItem.getId());
		
		redirectAttributes.addAttribute("status", true);
		
		return "redirect:/validation/v2/items/{itemId}";
		}