工作的时候突然想到一个问题,valid运行机制。为什么直接引入包就可以了,valid运行机制。为什么直接引入包就可以了??
启动程序的时候:
classLoader.getResources("META-INF/spring.factories") ; //获取所有查看有这个spring.factories文件的引入的jar包
在spring-boot-autoconfigure包里面的配置文件配置了需要启动时调用方法org.springframework.boot.autoconfigure.BackgroundPreinitializer
在org.springframework.boot.autoconfigre.BackgroundPreinitializer类 performPreinitialization()当中配置当中
//初始化ByteBuffer、字符串时区、时区时间转Calendar、对象之间转换、失败对象转字符串、对象转参数等等...
this.runSafely(new ConversionServiceInitializer());
//初始化校验模块(在这里...........)
this.runSafely(new ValidationInitializer());
//初始化消息转换模块 (支持消息转换模型
javax.xml.bind.Binder 、
com.fasterxml.jackson.databind.ObjectMapper 、
com.fasterxml.jackson.dataformat.xml.XmlMapper 、
com.fasterxml.jackson.dataformat.smile.SmileFactory 、
com.google.gson.Gson、
javax.json.bind.Jsonb
)
this.runSafely(new MessageConverterInitializer());
//初始化MBean模块 (涉及tomcat相关模块 StringManager 内置线程安全hashtable;javax.management.MBeanServer) JMX核心
this.runSafely(new MBeanFactoryInitializer());
this.runSafely(new JacksonInitializer());
//初始化字符集 UTF-8
this.runSafely(new CharsetInitializer());
//计数器-1
BackgroundPreinitializer.preinitializationComplete.countDown();
会预先加载 javax.validation.Validation.java中调用的configure()方法(在validation-api的jar包中)
configrure()内部会在Validation.java中的内部私有单例类调用run方法:
1.获取当前线程的上下文ClassLoader
2.根据ClassLoader获取缓存cachedContextClassLoaderProviderList 列表
3.如果缓存没有,则通过loadProviders()方法进行加载:
//java公共方法,将实现了javax.validation.spi.ValidationProvider接口的加载到LazyIterator 对象当中
java.util.ServiceLoader.load( ValidationProvider.class, classloader )
4.迭代里面找到实现了ValidationProvider接口的实例类 org.hibernate.validator.HibernateValidator
5.通过class.newInstance()进行实例化
6.这里可能会有实现多个ValidationProvider接口的实例类,但是在configrure()内部会在Validation.java 只会取第一个。
//自动加载就完成了..
请求调用接口是这样.......
1.启动的时候先找org.springframework.context.ApplicationContextInitializer 模块
2.在找org.springframework.context.ApplicationListener 模块
3.在找org.springframework.boot.autoconfigure.AutoConfigurationImportListener 模块
4.在找org.springframework.boot.autoconfigure.AutoConfigurationImportFilter 模块
5.在找org.springframework.boot.autoconfigure.EnableAutoConfiguration 模块
1.启动的时候在spring-boot-autoconfigure包里面的配置文件
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext 调用finishBeanFactoryInitialization(beanFactory)方法 创建服务.
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletContext servletContext)
org.springframework.boot.web.servlet.ServletContextInitializerBeans (添加servlet进去)
添加几种模式:
ServletRegistrationBean、
FilterRegistrationBean、
DelegatingFilterProxyRegistrationBean、
ServletListenerRegistrationBean、
或者ServletContextInitializer实现了接口的自定义Bean
请求接口的时候:(内部socket连接),建立连接
1.通过org.apache.tomcat.util.net.NioEndpoint 调用org.apache.coyote.AbstractProtocol.process()方法
2.process()内部调用org.apache.coyote.http11.Http11Processor.service()方法,
3.在service()里面进入了适配器(org.apache.catalina.connector.CoyoteAdapter)
4.在service()语法块中,postParseRequest(req, request, res, response);方法内设置了request、response基础信息
5.并在之后的this.connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
实际上是到...org.apache.catalina.core.StandardEngineValve.invoke(Request request, Response response)
通过连接得到服务、得到容器、得到管道、取第一个管道,进行回调
6.进一步到 -> org.apache.catalina.valves.ErrorReportValve.invoke(Request request, Response response) (这里处理servlet异常抛出问题)
7.进一步到 -> org.apache.catalina.core.StandardHostValve.invoke(Request request, Response response)
8.进一步到 -> org.apache.catalina.authenticator.AuthenticatorBase.invoke(Request request, Response response)
9.进一步到 -> org.apache.catalina.core.StandardContextValve.invoke(Request request, Response response)
10.进一步到-> org.apache.catalina.core.StandardWrapperValve.invoke(Request request, Response response)
在 org.apache.catalina.core.StandardWrapper.allocate() 加载【servlet(DisPatchServlet)】
在 request中设置 :org.apache.catalina.core.DISPATCHER_TYPE 和org.apache.catalina.core.DISPATCHER_REQUEST_PATH 参数
通过 StandardWrapper wrapper = (StandardWrapper)this.getContainer(); 得到wrapper
10.1.进一步到-> org.apache.catalina.core.ApplicationFilterFactory.createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet)
创建filterChain,并通过filterChain.setServlet(servlet) 将servlet 设置到filter里面
===============================
通过 StandardContext context = (StandardContext)wrapper.getParent();
FilterMap[] filterMaps = context.findFilterMaps(); 得到filterMap对象包含:
characterEncodingFilter、webMvcMetricsFilter、hiddenHttpMethodFilter、httpPutFormContentFilter、
requestContextFilter、
org.springframework.boot.actuate.web.trace.servlet.httpTraceFilter、Tomcat WebSocket (JSR356) Filter
这些Filter都继承了OncePerRequestFilter
================================
遍历filterMap 通过匹配Dispatch类型以及url或者servlet名称的 ,filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMaps[i].getFilterName()); 得到filterConfig对象
并依次通过 filterChain.addFilter(filterConfig)加入到加入到filter列表中
11.通过返回的filterChain.doFilter(request.getRequest(), response.getResponse()) 进行filter处理
12.进入org.springframework.web.filter.doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 处理filter
13.进入org.springframework.web.filter.OncePerRequestFilter.doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
通过抽象函数this.doFilterInternal(httpRequest, httpResponse, filterChain);调用对应的Filter实例方法
13.进入 org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
14....依次进入Filter 在httpTraceFilter->org.apache.tomcat.websocket.server.wsFilter之后。。进入servlet处理
15.org.springframework.web.servlet.doDispatch(HttpServletRequest request, HttpServletResponse response)进行分发
在方法内调用 mappedHandler.applyPreHandle(processedRequest, response) 获取拦截器列表
WebMvcConfig、ConversionServiceExposingInterceptor、ResourceUrlProviderExposingInterceptor
16.拦截器过后执行AbstractHandlerMethodAdapter.handler()
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handler(HttpServletRequest request, HttpServletResponse response, Object handler)
17.进入 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
进入 invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) 方法
18.进入org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs)
org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs)
org.springframework.web.method.support.resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory)
org.springframework.web.servlet.mvc.method.annotation.resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory)
执行了this.validateIfApplicable(binder, parameter);
会去找注解为@Validated 或者@Valid开头的注解校验(这里就可以自定义校验注解,只要是Valid开头的)
19.进入org.springframework.validation.DataBinder.validate(Object... validationHints)
org.springframework.boot.autoconfigure.validation.ValidatorAdapter.validate(Object target, Errors errors, Object... validationHints)
org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(@Nullable Object target, Errors errors, @Nullable Object... validationHints)
org.hibernate.validator.internal.engine.ValidatorImpl.validate(T object, Class<?>... groups) (实现了接口implements Validator, ExecutableValidator)
org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidationContext<T> validationContext, ValueContext<U, Object> valueContext, ValidationOrder validationOrder)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidationContext<?> validationContext, ValueContext<U, Object> valueContext)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidationContext<?> validationContext, ValueContext<U, Object> valueContext, Map<Class<?>, Class<?>> validatedInterfaces, Class<? super U> clazz, Set<MetaConstraint<?>> metaConstraints, Group defaultSequenceMember)
在这里while(true)遍历所有校验值....
org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext, Object parent, MetaConstraint<?> metaConstraint)
org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext)
org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(ValidationContext<?> executionContext, ValueContext<?, ?> valueContext)
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ValidationContext<T> executionContext, ValueContext<?, ?> valueContext)
org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(ValidationContext<T> validationContext, ValueContext<?, ?> valueContext, Set<ConstraintViolation<T>> constraintViolations)
ConstraintValidator<B, ?> validator = this.getInitializedConstraintValidator(validationContext, valueContext); (得到校验器)
ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl(validationContext.getParameterNames(), validationContext.getClockProvider(), valueContext.getPropertyPath(), this.descriptor, validationContext.getConstraintValidatorPayload());
this.validateSingleConstraint(validationContext, valueContext, constraintValidatorContext, validator)
在方法validateSingleConstraint(ValidationContext<T> executionContext, ValueContext<?, ?> valueContext, ConstraintValidatorContextImpl constraintValidatorContext, ConstraintValidator<A, V> validator)里面
V validatedValue = valueContext.getCurrentValidatedValue();
执行isValid = validator.isValid(validatedValue, constraintValidatorContext);进行校验