Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
Spring_resource_analysis
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
WeifengSun
Spring_resource_analysis
Commits
101c1853
Commit
101c1853
authored
Oct 08, 2022
by
SunWei峰
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
给昨天补一个push,今天继续加油
parent
ba2803d2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
74 additions
and
6 deletions
+74
-6
spring-framework-main/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodReturnValueHandlerComposite.java
+6
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java
+2
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.java
+2
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java
+6
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java
+38
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java
+5
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
+11
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
+3
-0
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractView.java
+1
-6
No files found.
spring-framework-main/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodReturnValueHandlerComposite.java
View file @
101c1853
...
...
@@ -71,20 +71,26 @@ public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodRe
public
void
handleReturnValue
(
@Nullable
Object
returnValue
,
MethodParameter
returnType
,
ModelAndViewContainer
mavContainer
,
NativeWebRequest
webRequest
)
throws
Exception
{
// 查找处理器
HandlerMethodReturnValueHandler
handler
=
selectHandler
(
returnValue
,
returnType
);
if
(
handler
==
null
)
{
throw
new
IllegalArgumentException
(
"Unknown return value type: "
+
returnType
.
getParameterType
().
getName
());
}
// 此处handler就是HandlerMethodReturnValueHandler的实现类
// HandlerMethodReturnValueHandler#handleReturnValue处理返回值
handler
.
handleReturnValue
(
returnValue
,
returnType
,
mavContainer
,
webRequest
);
}
@Nullable
private
HandlerMethodReturnValueHandler
selectHandler
(
@Nullable
Object
value
,
MethodParameter
returnType
)
{
boolean
isAsyncValue
=
isAsyncReturnValue
(
value
,
returnType
);
// returnValueHandlers就是HandlerMethodReturnValueHandler的实现类集合,默认有15个实现类
// 注意:returnValueHandlers是有顺序的
for
(
HandlerMethodReturnValueHandler
handler
:
this
.
returnValueHandlers
)
{
if
(
isAsyncValue
&&
!(
handler
instanceof
AsyncHandlerMethodReturnValueHandler
))
{
continue
;
}
// 使用supportsReturnType方法判断该处理器是否支持解析当前返回值
if
(
handler
.
supportsReturnType
(
returnType
))
{
return
handler
;
}
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java
View file @
101c1853
...
...
@@ -1322,7 +1322,9 @@ public class DispatcherServlet extends FrameworkServlet {
@Nullable
protected
HandlerExecutionChain
getHandler
(
HttpServletRequest
request
)
throws
Exception
{
if
(
this
.
handlerMappings
!=
null
)
{
// 这里的 HandlerMapping 如果没有特殊操作,则默认是从配置文件中读取并加载的 HandlerMapping
for
(
HandlerMapping
mapping
:
this
.
handlerMappings
)
{
// 调用HandlerMapping 的getHandler 方法。
HandlerExecutionChain
handler
=
mapping
.
getHandler
(
request
);
if
(
handler
!=
null
)
{
return
handler
;
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.java
View file @
101c1853
...
...
@@ -75,9 +75,11 @@ public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHand
// Take any bean name that we can determine URLs for.
for
(
String
beanName
:
beanNames
)
{
// 记录开头是 "/" 的 bean
String
[]
urls
=
determineUrlsForHandler
(
beanName
);
if
(!
ObjectUtils
.
isEmpty
(
urls
))
{
// URL paths found: Let's consider it a handler.
// 注册成handler
registerHandler
(
urls
,
beanName
);
}
}
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java
View file @
101c1853
...
...
@@ -495,7 +495,9 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
@Override
@Nullable
public
final
HandlerExecutionChain
getHandler
(
HttpServletRequest
request
)
throws
Exception
{
// 1. 调用 getHandlerInternal 获取 handler。该方法供子类实现。
Object
handler
=
getHandlerInternal
(
request
);
// 如果没有获取到 handler。则获取默认的handler
if
(
handler
==
null
)
{
handler
=
getDefaultHandler
();
}
...
...
@@ -503,6 +505,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
return
null
;
}
// Bean name or resolved handler?
// 如果 handler 是 String类型,则会认为是 beanName。从Spring容器中获取 bean实例
if
(
handler
instanceof
String
handlerName
)
{
handler
=
obtainApplicationContext
().
getBean
(
handlerName
);
}
...
...
@@ -512,6 +515,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
initLookupPath
(
request
);
}
// 2. 生成拦截器链路
HandlerExecutionChain
executionChain
=
getHandlerExecutionChain
(
handler
,
request
);
if
(
logger
.
isTraceEnabled
())
{
...
...
@@ -600,9 +604,11 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
* @see #getAdaptedInterceptors()
*/
protected
HandlerExecutionChain
getHandlerExecutionChain
(
Object
handler
,
HttpServletRequest
request
)
{
// 构建一个执行链
HandlerExecutionChain
chain
=
(
handler
instanceof
HandlerExecutionChain
handlerExecutionChain
?
handlerExecutionChain
:
new
HandlerExecutionChain
(
handler
));
// 遍历所有的拦截器,如果拦截器匹配符则加入到执行链中。adaptedInterceptors 是在 Mapping 初始化的时候加载的
for
(
HandlerInterceptor
interceptor
:
this
.
adaptedInterceptors
)
{
if
(
interceptor
instanceof
MappedInterceptor
mappedInterceptor
)
{
if
(
mappedInterceptor
.
matches
(
request
))
{
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java
View file @
101c1853
...
...
@@ -40,6 +40,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.core.MethodIntrospector
;
import
org.springframework.lang.Nullable
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.LinkedMultiValueMap
;
...
...
@@ -220,11 +221,15 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @see #handlerMethodsInitialized
*/
protected
void
initHandlerMethods
()
{
// getCandidateBeanNames(): 从 Spring 容器中获取所有候选的beanName。
for
(
String
beanName
:
getCandidateBeanNames
())
{
// 如果beanName 不是以 SCOPED_TARGET_NAME_PREFIX 开头,则进行处理
if
(!
beanName
.
startsWith
(
SCOPED_TARGET_NAME_PREFIX
))
{
// 1. 初始 候选的beanName
processCandidateBean
(
beanName
);
}
}
// 这里就是打印了一下log日志
handlerMethodsInitialized
(
getHandlerMethods
());
}
...
...
@@ -262,7 +267,9 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
logger
.
trace
(
"Could not resolve type for bean '"
+
beanName
+
"'"
,
ex
);
}
}
// 有 @controller 修饰或有 @RequestMapping修饰
if
(
beanType
!=
null
&&
isHandler
(
beanType
))
{
// 筛选出合适的 HandlerMethod 注册
detectHandlerMethods
(
beanName
);
}
}
...
...
@@ -273,14 +280,19 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @see #getMappingForMethod
*/
protected
void
detectHandlerMethods
(
Object
handler
)
{
// 获取 handlerType。这里传入的 handler如果是 String 就是 beanName,从上下文中获取type,否则就直接认为是 Handler
Class
<?>
handlerType
=
(
handler
instanceof
String
beanName
?
obtainApplicationContext
().
getType
(
beanName
)
:
handler
.
getClass
());
if
(
handlerType
!=
null
)
{
// 返回给定类的用户定义类:通常只是给定的类,但对于CGLIB生成的子类,则返回原始类
Class
<?>
userType
=
ClassUtils
.
getUserClass
(
handlerType
);
// 遍历当前bean的所有方法,筛选出合适的 handler 方法 以及 注解信息
// 这里需要注意的是 MethodIntrospector.selectMethods 底层将 getMappingForMethod 返回为 null 的值给过滤掉了
Map
<
Method
,
T
>
methods
=
MethodIntrospector
.
selectMethods
(
userType
,
(
MethodIntrospector
.
MetadataLookup
<
T
>)
method
->
{
try
{
// 供子类实现
return
getMappingForMethod
(
method
,
userType
);
}
catch
(
Throwable
ex
)
{
...
...
@@ -294,8 +306,11 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
else
if
(
mappingsLogger
.
isDebugEnabled
())
{
mappingsLogger
.
debug
(
formatMappings
(
userType
,
methods
));
}
// 遍历所有的 methods(这里的 methods 经过上面的筛选后,都是被 @RequestMapping 注解修饰的方法)
methods
.
forEach
((
method
,
mapping
)
->
{
// 这里是针对 cglib 代理特殊处理
Method
invocableMethod
=
AopUtils
.
selectInvocableMethod
(
method
,
userType
);
//注册 HandlerMethod
registerHandlerMethod
(
handler
,
invocableMethod
,
mapping
);
});
}
...
...
@@ -377,9 +392,11 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
@Override
@Nullable
protected
HandlerMethod
getHandlerInternal
(
HttpServletRequest
request
)
throws
Exception
{
// 从 request 中解析出 请求路径
String
lookupPath
=
initLookupPath
(
request
);
this
.
mappingRegistry
.
acquireReadLock
();
try
{
// 查找 HandlerMethod
HandlerMethod
handlerMethod
=
lookupHandlerMethod
(
lookupPath
,
request
);
return
(
handlerMethod
!=
null
?
handlerMethod
.
createWithResolvedBean
()
:
null
);
}
...
...
@@ -399,16 +416,25 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
*/
@Nullable
protected
HandlerMethod
lookupHandlerMethod
(
String
lookupPath
,
HttpServletRequest
request
)
throws
Exception
{
// 通过 url 获取匹配路径
// springMVC 会在初始化的时候建立 URL 和相应 RequestMappingInfo 的映射,这点在上面的解析中我们可以知道。
// 如果不是restful接口,这里就可以直接获取到。
// 这里是通过 urlLookup 获取的 RequestMappingInfo
List
<
Match
>
matches
=
new
ArrayList
<>();
List
<
T
>
directPathMatches
=
this
.
mappingRegistry
.
getMappingsByDirectPath
(
lookupPath
);
if
(
directPathMatches
!=
null
)
{
// 将匹配的 Mapping 保存到 matches 中。
addMatchingMappings
(
directPathMatches
,
matches
,
request
);
}
// 如果上面没有获取到匹配的路径,则只能遍历所有的 mapping。
// 由于会遍历所有的 RequestMapping。所以性能会随着 RequestMapping 数量的增加降低
if
(
matches
.
isEmpty
())
{
addMatchingMappings
(
this
.
mappingRegistry
.
getRegistrations
().
keySet
(),
matches
,
request
);
}
// 如果 matches 不为空,则说明有匹配的 Mapping
if
(!
matches
.
isEmpty
())
{
Match
bestMatch
=
matches
.
get
(
0
);
// 如果合适的 Mapping 不止一个,则筛选出最合适的
if
(
matches
.
size
()
>
1
)
{
Comparator
<
Match
>
comparator
=
new
MatchComparator
(
getMappingComparator
(
request
));
matches
.
sort
(
comparator
);
...
...
@@ -628,28 +654,40 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
}
public
void
register
(
T
mapping
,
Object
handler
,
Method
method
)
{
// 加写锁
this
.
readWriteLock
.
writeLock
().
lock
();
try
{
// 将 handler 和 method 封装成一个 HandlerMethod 实例
HandlerMethod
handlerMethod
=
createHandlerMethod
(
handler
,
method
);
// 校验实例的合法性。即唯一性
validateMethodMapping
(
handlerMethod
,
mapping
);
// 获取url映射,如果是 restful 请求则获取不到。建立 url 和Mapping 的映射。
// 一个mapping 可以对应多个url
Set
<
String
>
directPaths
=
AbstractHandlerMethodMapping
.
this
.
getDirectPaths
(
mapping
);
// 这里将url 和 mapping映射起来
// 在进行匹配的时候,就是先根据url找到合适的mapping,然后根据找到的mapping再去找到HandlerMethod
for
(
String
path
:
directPaths
)
{
this
.
pathLookup
.
add
(
path
,
mapping
);
}
// 保存 类名#方法名 : HandlerMethod 的映射关系
String
name
=
null
;
if
(
getNamingStrategy
()
!=
null
)
{
// 这里解析出来的 name 并不是完整的类名,而是类名的首字母组合。比如方法名是 DemoController.say(),
// 解析出来的name即为 DC#say。如果是 SayController.say()。解析出来则为 name = SC#say
name
=
getNamingStrategy
().
getName
(
handlerMethod
,
mapping
);
addMappingName
(
name
,
handlerMethod
);
}
// @CrossOrigin 跨域注解请求的初始化配置
CorsConfiguration
corsConfig
=
initCorsConfiguration
(
handler
,
method
,
mapping
);
if
(
corsConfig
!=
null
)
{
corsConfig
.
validateAllowCredentials
();
this
.
corsLookup
.
put
(
handlerMethod
,
corsConfig
);
}
// 保存到 registry 中
this
.
registry
.
put
(
mapping
,
new
MappingRegistration
<>(
mapping
,
handlerMethod
,
directPaths
,
name
,
corsConfig
!=
null
));
}
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java
View file @
101c1853
...
...
@@ -409,6 +409,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
Object
resolvedHandler
=
handler
;
// Eagerly resolve handler if referencing singleton via name.
// 如果不是懒加载 && handler 是 String 类型。
if
(!
this
.
lazyInitHandlers
&&
handler
instanceof
String
handlerName
)
{
ApplicationContext
applicationContext
=
obtainApplicationContext
();
if
(
applicationContext
.
isSingleton
(
handlerName
))
{
...
...
@@ -416,6 +417,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
}
}
// 判断 handlerMap 中已经保存了该 url
Object
mappedHandler
=
this
.
handlerMap
.
get
(
urlPath
);
if
(
mappedHandler
!=
null
)
{
if
(
mappedHandler
!=
resolvedHandler
)
{
...
...
@@ -425,12 +427,14 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
}
}
else
{
// 如果是 urlPath 是 "/" 开头。则设置为根处理器
if
(
urlPath
.
equals
(
"/"
))
{
if
(
logger
.
isTraceEnabled
())
{
logger
.
trace
(
"Root mapping to "
+
getHandlerDescription
(
handler
));
}
setRootHandler
(
resolvedHandler
);
}
// 如果是 urlPath 是 "/*" 开头。则设置为 默认处理器
else
if
(
urlPath
.
equals
(
"/*"
))
{
if
(
logger
.
isTraceEnabled
())
{
logger
.
trace
(
"Default mapping to "
+
getHandlerDescription
(
handler
));
...
...
@@ -438,6 +442,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
setDefaultHandler
(
resolvedHandler
);
}
else
{
// 否则的话,保存到 handlerMap 中
this
.
handlerMap
.
put
(
urlPath
,
resolvedHandler
);
if
(
getPatternParser
()
!=
null
)
{
this
.
pathPatternHandlerMap
.
put
(
getPatternParser
().
parse
(
urlPath
),
resolvedHandler
);
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
View file @
101c1853
...
...
@@ -187,6 +187,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@Override
@SuppressWarnings
(
"deprecation"
)
public
void
afterPropertiesSet
()
{
// 进行 RequestMapping 的配置
this
.
config
=
new
RequestMappingInfo
.
BuilderConfiguration
();
this
.
config
.
setTrailingSlashMatch
(
useTrailingSlashMatch
());
this
.
config
.
setContentNegotiationManager
(
getContentNegotiationManager
());
...
...
@@ -202,6 +203,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
this
.
config
.
setPathMatcher
(
getPathMatcher
());
}
// 调用父类的 afterPropertiesSet 方法。
super
.
afterPropertiesSet
();
}
...
...
@@ -279,12 +281,17 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@Override
@Nullable
protected
RequestMappingInfo
getMappingForMethod
(
Method
method
,
Class
<?>
handlerType
)
{
// 转换成 RequestMappingInfo,如果方法没有被 @RequestMapping 注解修饰,则会返回null
// 解析出来 方法 上 @RequestMapping 注解的各种信息
RequestMappingInfo
info
=
createRequestMappingInfo
(
method
);
if
(
info
!=
null
)
{
// 解析出来 bean 上 @RequestMapping 注解的各种信息
RequestMappingInfo
typeInfo
=
createRequestMappingInfo
(
handlerType
);
if
(
typeInfo
!=
null
)
{
// 合并类和方法的 @RequestMapping 注解信息
info
=
typeInfo
.
combine
(
info
);
}
// 获取前缀,拼接前缀
String
prefix
=
getPathPrefix
(
handlerType
);
if
(
prefix
!=
null
)
{
info
=
RequestMappingInfo
.
paths
(
prefix
).
options
(
this
.
config
).
build
().
combine
(
info
);
...
...
@@ -316,9 +323,12 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
*/
@Nullable
private
RequestMappingInfo
createRequestMappingInfo
(
AnnotatedElement
element
)
{
// 获取当前方法上的 @RequestMapping 注解
RequestMapping
requestMapping
=
AnnotatedElementUtils
.
findMergedAnnotation
(
element
,
RequestMapping
.
class
);
// 获取自定义的方法条件
RequestCondition
<?>
condition
=
(
element
instanceof
Class
?
getCustomTypeCondition
((
Class
<?>)
element
)
:
getCustomMethodCondition
((
Method
)
element
));
// 这里可以看到: 如果 requestMapping = null,则会直接返回 null,否则会封装成一个 RequestMappingInfo (包含 @RequestMapping 注解的各种参数) 返回。
return
(
requestMapping
!=
null
?
createRequestMappingInfo
(
requestMapping
,
condition
)
:
null
);
}
...
...
@@ -420,6 +430,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
}
private
void
updateConsumesCondition
(
RequestMappingInfo
info
,
Method
method
)
{
// 对 @RequestBody 注解进行了进一步解析
ConsumesRequestCondition
condition
=
info
.
getConsumesCondition
();
if
(!
condition
.
isEmpty
())
{
for
(
Parameter
parameter
:
method
.
getParameters
())
{
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
View file @
101c1853
...
...
@@ -114,6 +114,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
public
void
invokeAndHandle
(
ServletWebRequest
webRequest
,
ModelAndViewContainer
mavContainer
,
Object
...
providedArgs
)
throws
Exception
{
// 调用handler(controller+method),得到返回值
Object
returnValue
=
invokeForRequest
(
webRequest
,
mavContainer
,
providedArgs
);
setResponseStatus
(
webRequest
);
...
...
@@ -132,6 +133,8 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
mavContainer
.
setRequestHandled
(
false
);
Assert
.
state
(
this
.
returnValueHandlers
!=
null
,
"No return value handlers"
);
try
{
// 处理返回值方法
// returnValueHandlers是HandlerMethodReturnValueHandlerComposite类
this
.
returnValueHandlers
.
handleReturnValue
(
returnValue
,
getReturnValueType
(
returnValue
),
mavContainer
,
webRequest
);
}
...
...
spring-framework-main/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractView.java
View file @
101c1853
...
...
@@ -18,12 +18,7 @@ package org.springframework.web.servlet.view;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
java.util.Properties
;
import
java.util.Set
;
import
java.util.StringTokenizer
;
import
java.util.*
;
import
jakarta.servlet.ServletOutputStream
;
import
jakarta.servlet.http.HttpServletRequest
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment