@@ -8004,6 +8004,8 @@ AbstractAutowireCapableBeanFactory.createBeanInstance(beanName, RootBeanDefiniti
80048004
80058005* 判断类的访问权限是不是 public,不是进入下一个判断,是否允许访问类的 non-public 的构造方法,不允许则报错
80068006
8007+ * `Supplier<?> instanceSupplier = mbd.getInstanceSupplier()`:获取创建实例的函数,可以自定义,没有进入下面的逻辑
8008+
80078009* `if (mbd.getFactoryMethodName() != null)`:**判断 bean 是否设置了 factory-method 属性**
80088010
80098011 <bean class=" " factory-method=" " >,设置了该属性进入 factory-method 方法创建实例
@@ -8017,13 +8019,13 @@ AbstractAutowireCapableBeanFactory.createBeanInstance(beanName, RootBeanDefiniti
80178019 * method 为 null 则 resolved 和 autowireNecessary 都为默认值 false
80188020 * `autowireNecessary = mbd.constructorArgumentsResolved`:构造方法有参数,设置为 true
80198021
8020- * bd 对应的构造信息解析完成:
8022+ * ** bd 对应的构造信息解析完成,可以直接反射调用构造方法了** :
80218023
80228024 * `return autowireConstructor(beanName, mbd, null, null)`:**有参构造**,根据参数匹配最优的构造器创建实例
80238025
80248026 * `return instantiateBean(beanName, mbd)`:**无参构造方法通过反射创建实例**
80258027
8026- * `ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName)`:**AutowiredAnnotation 逻辑**
8028+ * `ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName)`:@Autowired 注解对应的后置处理器**AutowiredAnnotationBeanPostProcessor 逻辑**
80278029
80288030 * 配置了 lookup 的相关逻辑
80298031
@@ -8080,7 +8082,7 @@ AbstractAutowireCapableBeanFactory.createBeanInstance(beanName, RootBeanDefiniti
80808082
80818083 `!ObjectUtils.isEmpty(args)`:getBean 时,指定了参数 arg
80828084
8083- * `autowireConstructor(beanName, mbd, ctors, args)`:**选择最优的构造器进行创建实例**(非常复杂,可以放弃深究 )
8085+ * `return autowireConstructor(beanName, mbd, ctors, args)`:**选择最优的构造器进行创建实例**(复杂,不建议研究 )
80848086
80858087 * `beanFactory.initBeanWrapper(bw)`:向 BeanWrapper 中注册转换器,向工厂中注册属性编辑器
80868088
@@ -8157,13 +8159,19 @@ AbstractAutowireCapableBeanFactory.createBeanInstance(beanName, RootBeanDefiniti
81578159
81588160 * ` bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse))`:匹配成功调用 instantiate 创建出实例对象,设置到 BeanWrapper 中去
81598161
8160- * `SimpleInstantiationStrategy.instantiate( )`:**真正用来实例化的函数**(无论如何都会走到这一步)
8162+ * `return instantiateBean(beanName, mbd )`:默认走到这里
81618163
8162- * `if (!bd.hasMethodOverrides())`:没有方法重写覆盖
8164+ * `SimpleInstantiationStrategy.instantiate()`:**真正用来实例化的函数**(无论如何都会走到这一步)
81638165
8164- `BeanUtils.instantiateClass(constructorToUse)`:底层调用 java.lang.reflect.Constructor.newInstance() 实例化
8166+ * `if (!bd.hasMethodOverrides())`:没有方法重写覆盖
81658167
8166- * `instantiateWithMethodInjection(bd, beanName, owner)`:有方法重写采用 CGLIB 实例化
8168+ `BeanUtils.instantiateClass(constructorToUse)`:调用 `java.lang.reflect.Constructor.newInstance()` 实例化
8169+
8170+ * `instantiateWithMethodInjection(bd, beanName, owner)`:有方法重写采用 CGLIB 实例化
8171+
8172+ * `BeanWrapper bw = new BeanWrapperImpl(beanInstance)`:包装成 BeanWrapper 类型的对象
8173+
8174+ * `return bw`:返回实例
81678175
81688176
81698177
@@ -9760,10 +9768,39 @@ SpringMVC 对接收的数据进行自动类型转换,该工作通过 Converter
97609768
97619769##### 自定义
97629770
9763- * 自定义类型转换器,实现 Converter 接口,并制定转换前与转换后的类型
9771+ 自定义类型转换器,实现 Converter 接口或者直接容器中注入:
9772+
9773+ * 方式一:
9774+
9775+ ```java
9776+ public class WebConfig implements WebMvcConfigurer {
9777+ @Bean
9778+ public WebMvcConfigurer webMvcConfigurer() {
9779+ return new WebMvcConfigurer() {
9780+ @Override
9781+ public void addFormatters(FormatterRegistry registry) {
9782+ registry.addConverter(new Converter<String, Date>() {
9783+ @Override
9784+ public Pet convert(String source) {
9785+ DateFormat df = new SimpleDateFormat(" yyyy-MM-dd" );
9786+ Date date = null;
9787+ //类型转换器无法预计使用过程中出现的异常,因此必须在类型转换器内部捕获,
9788+ //不允许抛出,框架无法预计此类异常如何处理
9789+ try {
9790+ date = df.parse(source);
9791+ } catch (ParseException e) {
9792+ e.printStackTrace();
9793+ }
9794+ return date;
9795+ }
9796+ });
9797+ }
9798+ }
9799+ }
9800+
9801+ * 方式二:
97649802
97659803 ```java
9766- //自定义类型转换器,实现Converter接口,接口中指定的泛型即为最终作用的条件
97679804 //本例中的泛型填写的是String,Date,最终出现字符串转日期时,该类型转换器生效
97689805 public class MyDateConverter implements Converter<String, Date> {
97699806 //重写接口的抽象方法,参数由泛型决定
@@ -9782,7 +9819,7 @@ SpringMVC 对接收的数据进行自动类型转换,该工作通过 Converter
97829819 }
97839820 ```
97849821
9785- * 配置 resources / spring-mvc.xml,注册自定义转换器,将功能加入到 SpringMVC 转换服务 ConverterService 中
9822+ 配置 resources / spring-mvc.xml,注册自定义转换器,将功能加入到 SpringMVC 转换服务 ConverterService 中
97869823
97879824 ```xml
97889825 <!--1.将自定义Converter注册为Bean,受SpringMVC管理-->
@@ -9900,9 +9937,10 @@ SpringMVC 对接收的数据进行自动类型转换,该工作通过 Converter
99009937
99019938
99029939
9903- #### 带数据跳转
9940+ #### 数据跳转
9941+
9942+ ModelAndView 是 SpringMVC 提供的一个对象,该对象可以用作控制器方法的返回值(Model 同),实现携带数据跳转
99049943
9905- ModelAndView 是 SpringMVC 提供的一个对象,该对象可以用作控制器方法的返回值(Model 同)
99069944作用:
99079945
99089946+ 设置数据,向请求域对象中存储数据
@@ -9989,13 +10027,13 @@ ModelAndView 是 SpringMVC 提供的一个对象,该对象可以用作控制
998910027
999010028
999110029
9992- #### JSON数据
10030+ #### JSON
999310031
999410032注解:@ResponseBody
999510033
999610034作用:将 Controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到 Response 的 body 区。如果返回值是字符串,那么直接将字符串返回客户端;如果是一个对象,会**将对象转化为 Json**,返回客户端
999710035
9998- 注意:当方法上面没有写 ResponseBody,底层会将方法的返回值封装为 ModelAndView 对象。
10036+ 注意:当方法上面没有写 ResponseBody,底层会将方法的返回值封装为 ModelAndView 对象
999910037
1000010038* 使用 HttpServletResponse 对象响应数据
1000110039
@@ -10242,11 +10280,11 @@ public String getMessage(@PathVariable("id") Integer id){
1024210280
1024310281* @RequestHeader:获取请求头
1024410282* @RequestParam:获取请求参数(指问号后的参数,url?a=1&b=2)
10245- * @CookieValue:获取Cookie值
10246- * @RequestAttribute:获取request域属性
10247- * @RequestBody:获取请求体[POST]
10283+ * @CookieValue:获取 Cookie 值
10284+ * @RequestAttribute:获取 request 域属性
10285+ * @RequestBody:获取请求体 [POST]
1024810286* @MatrixVariable:矩阵变量
10249- * @ModelAttribute
10287+ * @ModelAttribute:自定义类型变量
1025010288
1025110289```java
1025210290@RestController
@@ -10355,105 +10393,6 @@ public class WebConfig{
1035510393
1035610394
1035710395
10358-
10359-
10360- ****
10361-
10362-
10363-
10364- ### 原理解析
10365-
10366- 请求进入原生的 HttpServlet 的 doGet() 方法处理,调用子类 FrameworkServlet 的 doGet() 方法,最终调用 DispatcherServlet 的 doService() 方法,为请求设置相关属性后调用 doDispatch()
10367-
10368- 
10369-
10370- 总体流程:
10371-
10372- * 所有的请求映射都在 HandlerMapping 中,RequestMappingHandlerMapping 处理 @RequestMapping 注解的所有映射规则
10373-
10374- * 请求进来,遍历所有的 HandlerMapping 看是否有请求信息,匹配成功后返回,匹配失败设置 HTTP 响应码
10375- * 用户可以自定义的映射处理,也可以给容器中放入自定义 HandlerMapping
10376-
10377- 访问 URL:http://localhost:8080/user(对应 Restful 中配置的映射规则)
10378-
10379- ```java
10380- protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
10381- HttpServletRequest processedRequest = request;
10382- HandlerExecutionChain mappedHandler = null;
10383- boolean multipartRequestParsed = false; //文件上传请求
10384- WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);//异步管理器
10385- try {
10386- //文件上传请求
10387- processedRequest = checkMultipart(request);
10388- // 找到当前请求使用哪个Handler(Controller的方法)处理
10389- mappedHandler = getHandler(processedRequest);
10390- // 没有合适的处理请求的方式 handler 直接返回
10391- if (mappedHandler == null) {
10392- noHandlerFound(processedRequest, response);
10393- return;
10394- }
10395- //...
10396- }
10397- }
10398- ```
10399-
10400- * HandlerMapping 处理器映射器,保存了所有 `@RequestMapping` 和 `handler` 的映射规则
10401-
10402- ```java
10403- protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
10404- if (this.handlerMappings != null) {
10405- //遍历所有的 HandlerMapping
10406- for (HandlerMapping mapping : this.handlerMappings) {
10407- //尝试去每个 HandlerMapping 中匹配当前请求的处理
10408- HandlerExecutionChain handler = mapping.getHandler(request);
10409- if (handler != null) {
10410- return handler;
10411- }
10412- }
10413- }
10414- return null;
10415- }
10416- ```
10417-
10418- 
10419-
10420- * `mapping.getHandler(request)` 中调用 `Object handler = getHandlerInternal(request)`,该 getHandlerInternal 方法是
10421-
10422- RequestMappingInfoHandlerMapping 类中的,继续调用 `AbstractHandlerMethodMapping.getHandlerInternal()`
10423-
10424- * AbstractHandlerMethodMapping.getHandlerInternal():
10425-
10426- ```java
10427- protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
10428- // lookupPath = user,地址栏的 uri
10429- String lookupPath = initLookupPath(request);
10430- // 防止并发
10431- this.mappingRegistry.acquireReadLock();
10432- try {
10433- //获取当前 HandlerMapping 中的映射规则
10434- HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
10435- return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
10436- }
10437- finally {
10438- this.mappingRegistry.releaseReadLock();
10439- }
10440- }
10441- ```
10442-
10443- * AbstractHandlerMethodMapping.lookupHandlerMethod():
10444-
10445- * `directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath)`:获取与 URI 相关的映射规则
10446-
10447- 
10448-
10449- * `addMatchingMappings(directPathMatches, matches, request)`:匹配某个映射规则
10450-
10451- * `Match bestMatch = matches.get(0)`:匹配完成只剩一个,直接获取返回对应的方法
10452-
10453- * `if (matches.size() > 1)`:当有多个映射规则符合请求时,报错
10454-
10455-
10456-
1045710396***
1045810397
1045910398
@@ -11783,6 +11722,22 @@ jsp:
1178311722
1178411723
1178511724
11725+ ***
11726+
11727+
11728+
11729+ ## 运行原理
11730+
11731+
11732+
11733+
11734+
11735+
11736+
11737+
11738+
11739+
11740+
1178611741
1178711742
1178811743***
0 commit comments