Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
3157b68e
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3157b68e
编写于
6月 28, 2013
作者:
P
Phillip Webb
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Polish MethodReference
Polish MethodReference code formatting and remove duplicate code.
上级
bf4563e2
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
132 addition
and
170 deletion
+132
-170
spring-expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java
.../springframework/expression/spel/ast/MethodReference.java
+132
-170
未找到文件。
spring-expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java
浏览文件 @
3157b68e
...
...
@@ -42,135 +42,123 @@ import org.springframework.expression.spel.SpelMessage;
*/
public
class
MethodReference
extends
SpelNodeImpl
{
private
final
String
name
;
private
final
boolean
nullSafe
;
private
final
String
name
;
private
volatile
CachedMethodExecutor
cachedExecutor
;
public
MethodReference
(
boolean
nullSafe
,
String
methodName
,
int
pos
,
SpelNodeImpl
...
arguments
)
{
public
MethodReference
(
boolean
nullSafe
,
String
methodName
,
int
pos
,
SpelNodeImpl
...
arguments
)
{
super
(
pos
,
arguments
);
this
.
name
=
methodName
;
this
.
nullSafe
=
nullSafe
;
this
.
name
=
methodName
;
}
public
final
String
getName
()
{
return
this
.
name
;
}
@Override
protected
ValueRef
getValueRef
(
ExpressionState
state
)
throws
EvaluationException
{
TypedValue
currentContext
=
state
.
getActiveContextObject
();
Object
[]
arguments
=
new
Object
[
getChildCount
()];
for
(
int
i
=
0
;
i
<
arguments
.
length
;
i
++)
{
// Make the root object the active context again for evaluating the parameter
// expressions
try
{
state
.
pushActiveContextObject
(
state
.
getRootContextObject
());
arguments
[
i
]
=
this
.
children
[
i
].
getValueInternal
(
state
).
getValue
();
}
finally
{
state
.
popActiveContextObject
();
}
}
if
(
currentContext
.
getValue
()
==
null
)
{
if
(
this
.
nullSafe
)
{
return
ValueRef
.
NullValueRef
.
instance
;
}
else
{
throw
new
SpelEvaluationException
(
getStartPosition
(),
SpelMessage
.
METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED
,
FormatHelper
.
formatMethodForMessage
(
this
.
name
,
getTypes
(
arguments
)));
}
Object
[]
arguments
=
getArguments
(
state
);
if
(
state
.
getActiveContextObject
().
getValue
()
==
null
)
{
throwIfNotNullSafe
(
getArgumentTypes
(
arguments
));
return
ValueRef
.
NullValueRef
.
instance
;
}
return
new
MethodValueRef
(
state
,
state
.
getEvaluationContext
(),
state
.
getActiveContextObject
().
getValue
(),
arguments
);
return
new
MethodValueRef
(
state
);
}
@Override
public
TypedValue
getValueInternal
(
ExpressionState
state
)
throws
EvaluationException
{
TypedValue
currentContext
=
state
.
getActiveContextObject
();
Object
[]
arguments
=
new
Object
[
getChildCount
()];
for
(
int
i
=
0
;
i
<
arguments
.
length
;
i
++)
{
// Make the root object the active context again for evaluating the parameter
// expressions
try
{
state
.
pushActiveContextObject
(
state
.
getRootContextObject
());
arguments
[
i
]
=
this
.
children
[
i
].
getValueInternal
(
state
).
getValue
();
}
finally
{
state
.
popActiveContextObject
();
}
}
TypedValue
activeContextObject
=
state
.
getActiveContextObject
();
TypeDescriptor
target
=
(
activeContextObject
==
null
?
null
:
activeContextObject
.
getTypeDescriptor
());
List
<
TypeDescriptor
>
argumentTypes
=
getTypes
(
arguments
);
if
(
currentContext
.
getValue
()
==
null
)
{
if
(
this
.
nullSafe
)
{
return
TypedValue
.
NULL
;
}
else
{
throw
new
SpelEvaluationException
(
getStartPosition
(),
SpelMessage
.
METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED
,
FormatHelper
.
formatMethodForMessage
(
this
.
name
,
argumentTypes
));
}
EvaluationContext
evaluationContext
=
state
.
getEvaluationContext
();
Object
value
=
state
.
getActiveContextObject
().
getValue
();
TypeDescriptor
targetType
=
state
.
getActiveContextObject
().
getTypeDescriptor
();
Object
[]
arguments
=
getArguments
(
state
);
return
getValueInternal
(
evaluationContext
,
value
,
arguments
,
targetType
);
}
private
TypedValue
getValueInternal
(
EvaluationContext
evaluationContext
,
Object
value
,
Object
[]
arguments
,
TypeDescriptor
targetType
)
{
List
<
TypeDescriptor
>
argumentTypes
=
getArgumentTypes
(
arguments
);
if
(
value
==
null
)
{
throwIfNotNullSafe
(
argumentTypes
);
return
TypedValue
.
NULL
;
}
MethodExecutor
executorToUse
=
getCachedExecutor
(
target
,
argumentTypes
);
MethodExecutor
executorToUse
=
getCachedExecutor
(
targetType
,
argumentTypes
);
if
(
executorToUse
!=
null
)
{
try
{
return
executorToUse
.
execute
(
state
.
getEvaluationContext
(),
state
.
getActiveContextObject
().
getValue
(),
arguments
);
return
executorToUse
.
execute
(
evaluationContext
,
value
,
arguments
);
}
catch
(
AccessException
ae
)
{
// Two reasons this can occur:
// 1. the method invoked actually threw a real exception
// 2. the method invoked was not passed the arguments it expected and has become 'stale'
// 2. the method invoked was not passed the arguments it expected and
// has become 'stale'
// In the first case we should not retry, in the second case we should see
if there is a
// better suited method.
// In the first case we should not retry, in the second case we should see
//
if there is a
better suited method.
// To determine which situation it is, the AccessException will contain a cause.
// If the cause is an InvocationTargetException, a user exception was thrown inside the method.
// To determine the situation, the AccessException will contain a cause.
// If the cause is an InvocationTargetException, a user exception was
// thrown inside the method.
// Otherwise the method could not be invoked.
throwSimpleExceptionIfPossible
(
stat
e
,
ae
);
throwSimpleExceptionIfPossible
(
valu
e
,
ae
);
// at this point we know it wasn't a user problem so worth a retry if a better candidate can be found
// at this point we know it wasn't a user problem so worth a retry if a
// better candidate can be found
this
.
cachedExecutor
=
null
;
}
}
// either there was no accessor or it no longer existed
executorToUse
=
findAccessorForMethod
(
this
.
name
,
argumentTypes
,
state
);
this
.
cachedExecutor
=
new
CachedMethodExecutor
(
executorToUse
,
target
,
argumentTypes
);
executorToUse
=
findAccessorForMethod
(
this
.
name
,
argumentTypes
,
value
,
evaluationContext
);
this
.
cachedExecutor
=
new
CachedMethodExecutor
(
executorToUse
,
targetType
,
argumentTypes
);
try
{
return
executorToUse
.
execute
(
state
.
getEvaluationContext
()
,
state
.
getActiveContextObject
().
getValue
()
,
arguments
);
return
executorToUse
.
execute
(
evaluationContext
,
value
,
arguments
);
}
catch
(
AccessException
ae
)
{
catch
(
AccessException
ex
)
{
// Same unwrapping exception handling as above in above catch block
throwSimpleExceptionIfPossible
(
state
,
ae
);
throw
new
SpelEvaluationException
(
getStartPosition
(),
ae
,
SpelMessage
.
EXCEPTION_DURING_METHOD_INVOCATION
,
this
.
name
,
state
.
getActiveContextObject
().
getValue
().
getClass
().
getName
(),
ae
.
getMessage
());
throwSimpleExceptionIfPossible
(
value
,
ex
);
throw
new
SpelEvaluationException
(
getStartPosition
(),
ex
,
SpelMessage
.
EXCEPTION_DURING_METHOD_INVOCATION
,
this
.
name
,
value
.
getClass
().
getName
(),
ex
.
getMessage
());
}
}
/**
* Decode the AccessException, throwing a lightweight evaluation exception or, if the cause was a RuntimeException,
* throw the RuntimeException directly.
*/
private
void
throwSimpleExceptionIfPossible
(
ExpressionState
state
,
AccessException
ae
)
{
if
(
ae
.
getCause
()
instanceof
InvocationTargetException
)
{
Throwable
rootCause
=
ae
.
getCause
().
getCause
();
if
(
rootCause
instanceof
RuntimeException
)
{
throw
(
RuntimeException
)
rootCause
;
private
void
throwIfNotNullSafe
(
List
<
TypeDescriptor
>
argumentTypes
)
{
if
(!
this
.
nullSafe
)
{
throw
new
SpelEvaluationException
(
getStartPosition
(),
SpelMessage
.
METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED
,
FormatHelper
.
formatMethodForMessage
(
this
.
name
,
argumentTypes
));
}
}
private
Object
[]
getArguments
(
ExpressionState
state
)
{
Object
[]
arguments
=
new
Object
[
getChildCount
()];
for
(
int
i
=
0
;
i
<
arguments
.
length
;
i
++)
{
// Make the root object the active context again for evaluating the parameter
// expressions
try
{
state
.
pushActiveContextObject
(
state
.
getRootContextObject
());
arguments
[
i
]
=
this
.
children
[
i
].
getValueInternal
(
state
).
getValue
();
}
finally
{
state
.
popActiveContextObject
();
}
throw
new
ExpressionInvocationTargetException
(
getStartPosition
(),
"A problem occurred when trying to execute method '"
+
this
.
name
+
"' on object of type '"
+
state
.
getActiveContextObject
().
getValue
().
getClass
().
getName
()
+
"'"
,
rootCause
);
}
return
arguments
;
}
private
List
<
TypeDescriptor
>
getTypes
(
Object
...
arguments
)
{
private
List
<
TypeDescriptor
>
get
Argument
Types
(
Object
...
arguments
)
{
List
<
TypeDescriptor
>
descriptors
=
new
ArrayList
<
TypeDescriptor
>(
arguments
.
length
);
for
(
Object
argument
:
arguments
)
{
descriptors
.
add
(
TypeDescriptor
.
forObject
(
argument
));
...
...
@@ -178,37 +166,25 @@ public class MethodReference extends SpelNodeImpl {
return
Collections
.
unmodifiableList
(
descriptors
);
}
@Override
public
String
toStringAST
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
this
.
name
).
append
(
"("
);
for
(
int
i
=
0
;
i
<
getChildCount
();
i
++)
{
if
(
i
>
0
)
{
sb
.
append
(
","
);
}
sb
.
append
(
getChild
(
i
).
toStringAST
());
private
MethodExecutor
getCachedExecutor
(
TypeDescriptor
target
,
List
<
TypeDescriptor
>
argumentTypes
)
{
if
(
this
.
cachedExecutor
!=
null
&&
this
.
cachedExecutor
.
isSuitable
(
target
,
argumentTypes
))
{
return
this
.
cachedExecutor
.
get
();
}
sb
.
append
(
")"
)
;
return
sb
.
toString
()
;
this
.
cachedExecutor
=
null
;
return
null
;
}
private
MethodExecutor
findAccessorForMethod
(
String
name
,
List
<
TypeDescriptor
>
argumentTypes
,
ExpressionState
state
)
throws
SpelEvaluationException
{
return
findAccessorForMethod
(
name
,
argumentTypes
,
state
.
getActiveContextObject
().
getValue
(),
state
.
getEvaluationContext
());
}
List
<
TypeDescriptor
>
argumentTypes
,
Object
contextObject
,
EvaluationContext
evaluationContext
)
throws
SpelEvaluationException
{
private
MethodExecutor
findAccessorForMethod
(
String
name
,
List
<
TypeDescriptor
>
argumentTypes
,
Object
contextObject
,
EvaluationContext
eContext
)
throws
SpelEvaluationException
{
List
<
MethodResolver
>
methodResolvers
=
eContext
.
getMethodResolvers
();
List
<
MethodResolver
>
methodResolvers
=
evaluationContext
.
getMethodResolvers
();
if
(
methodResolvers
!=
null
)
{
for
(
MethodResolver
methodResolver
:
methodResolvers
)
{
try
{
MethodExecutor
methodExecutor
=
methodResolver
.
resolve
(
eContext
,
contextObject
,
name
,
argumentTypes
);
MethodExecutor
methodExecutor
=
methodResolver
.
resolve
(
evaluationContext
,
contextObject
,
name
,
argumentTypes
);
if
(
methodExecutor
!=
null
)
{
return
methodExecutor
;
}
...
...
@@ -220,89 +196,71 @@ public class MethodReference extends SpelNodeImpl {
}
}
}
throw
new
SpelEvaluationException
(
getStartPosition
(),
SpelMessage
.
METHOD_NOT_FOUND
,
throw
new
SpelEvaluationException
(
getStartPosition
(),
SpelMessage
.
METHOD_NOT_FOUND
,
FormatHelper
.
formatMethodForMessage
(
name
,
argumentTypes
),
FormatHelper
.
formatClassNameForMessage
(
contextObject
instanceof
Class
?
((
Class
<?>)
contextObject
)
:
contextObject
.
getClass
()));
FormatHelper
.
formatClassNameForMessage
(
contextObject
instanceof
Class
?
((
Class
<?>)
contextObject
)
:
contextObject
.
getClass
()));
}
private
MethodExecutor
getCachedExecutor
(
TypeDescriptor
target
,
List
<
TypeDescriptor
>
argumentTypes
)
{
if
(
this
.
cachedExecutor
==
null
||
!
this
.
cachedExecutor
.
isSuitable
(
target
,
argumentTypes
))
{
this
.
cachedExecutor
=
null
;
return
null
;
/**
* Decode the AccessException, throwing a lightweight evaluation exception or, if the
* cause was a RuntimeException, throw the RuntimeException directly.
*/
private
void
throwSimpleExceptionIfPossible
(
Object
value
,
AccessException
ae
)
{
if
(
ae
.
getCause
()
instanceof
InvocationTargetException
)
{
Throwable
rootCause
=
ae
.
getCause
().
getCause
();
if
(
rootCause
instanceof
RuntimeException
)
{
throw
(
RuntimeException
)
rootCause
;
}
throw
new
ExpressionInvocationTargetException
(
getStartPosition
(),
"A problem occurred when trying to execute method '"
+
this
.
name
+
"' on object of type '"
+
value
.
getClass
().
getName
()
+
"'"
,
rootCause
);
}
return
this
.
cachedExecutor
.
get
();
}
@Override
public
String
toStringAST
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
this
.
name
).
append
(
"("
);
for
(
int
i
=
0
;
i
<
getChildCount
();
i
++)
{
if
(
i
>
0
)
{
sb
.
append
(
","
);
}
sb
.
append
(
getChild
(
i
).
toStringAST
());
}
sb
.
append
(
")"
);
return
sb
.
toString
();
}
private
class
MethodValueRef
implements
ValueRef
{
private
final
ExpressionState
state
;
private
final
EvaluationContext
evaluationContext
;
private
EvaluationContext
evaluationContext
;
private
final
Object
target
;
private
Object
value
;
private
TypeDescriptor
targetType
;
private
final
Object
[]
arguments
;
private
List
<
TypeDescriptor
>
argumentTypes
;
private
Object
[]
arguments
;
MethodValueRef
(
ExpressionState
state
,
EvaluationContext
evaluationContext
,
Object
object
,
Object
[]
arguments
)
{
this
.
state
=
state
;
this
.
evaluationContext
=
evaluationContext
;
this
.
target
=
object
;
this
.
targetType
=
TypeDescriptor
.
valueOf
(
target
.
getClass
());
this
.
arguments
=
arguments
;
this
.
argumentTypes
=
getTypes
(
this
.
arguments
);
MethodValueRef
(
ExpressionState
state
)
{
this
.
evaluationContext
=
state
.
getEvaluationContext
();
this
.
value
=
state
.
getActiveContextObject
().
getValue
();
this
.
targetType
=
state
.
getActiveContextObject
().
getTypeDescriptor
();
this
.
arguments
=
getArguments
(
state
);
}
@Override
public
TypedValue
getValue
()
{
MethodExecutor
executorToUse
=
getCachedExecutor
(
this
.
targetType
,
this
.
argumentTypes
);
if
(
executorToUse
!=
null
)
{
try
{
return
executorToUse
.
execute
(
this
.
evaluationContext
,
this
.
target
,
this
.
arguments
);
}
catch
(
AccessException
ae
)
{
// Two reasons this can occur:
// 1. the method invoked actually threw a real exception
// 2. the method invoked was not passed the arguments it expected and has become 'stale'
// In the first case we should not retry, in the second case we should see if there is a
// better suited method.
// To determine which situation it is, the AccessException will contain a cause.
// If the cause is an InvocationTargetException, a user exception was thrown inside the method.
// Otherwise the method could not be invoked.
throwSimpleExceptionIfPossible
(
this
.
state
,
ae
);
// at this point we know it wasn't a user problem so worth a retry if a better candidate can be found
MethodReference
.
this
.
cachedExecutor
=
null
;
}
}
// either there was no accessor or it no longer existed
executorToUse
=
findAccessorForMethod
(
MethodReference
.
this
.
name
,
argumentTypes
,
this
.
target
,
this
.
evaluationContext
);
MethodReference
.
this
.
cachedExecutor
=
new
CachedMethodExecutor
(
executorToUse
,
this
.
targetType
,
this
.
argumentTypes
);
try
{
return
executorToUse
.
execute
(
this
.
evaluationContext
,
this
.
target
,
this
.
arguments
);
}
catch
(
AccessException
ex
)
{
// Same unwrapping exception handling as above in above catch block
throwSimpleExceptionIfPossible
(
this
.
state
,
ex
);
throw
new
SpelEvaluationException
(
getStartPosition
(),
ex
,
SpelMessage
.
EXCEPTION_DURING_METHOD_INVOCATION
,
MethodReference
.
this
.
name
,
this
.
state
.
getActiveContextObject
().
getValue
().
getClass
().
getName
(),
ex
.
getMessage
());
}
return
MethodReference
.
this
.
getValueInternal
(
this
.
evaluationContext
,
this
.
value
,
this
.
arguments
,
this
.
targetType
);
}
@Override
...
...
@@ -316,6 +274,7 @@ public class MethodReference extends SpelNodeImpl {
}
}
private
static
class
CachedMethodExecutor
{
private
final
MethodExecutor
methodExecutor
;
...
...
@@ -324,6 +283,7 @@ public class MethodReference extends SpelNodeImpl {
private
final
List
<
TypeDescriptor
>
argumentTypes
;
public
CachedMethodExecutor
(
MethodExecutor
methodExecutor
,
TypeDescriptor
target
,
List
<
TypeDescriptor
>
argumentTypes
)
{
this
.
methodExecutor
=
methodExecutor
;
...
...
@@ -331,7 +291,9 @@ public class MethodReference extends SpelNodeImpl {
this
.
argumentTypes
=
argumentTypes
;
}
public
boolean
isSuitable
(
TypeDescriptor
target
,
List
<
TypeDescriptor
>
argumentTypes
)
{
public
boolean
isSuitable
(
TypeDescriptor
target
,
List
<
TypeDescriptor
>
argumentTypes
)
{
return
(
this
.
methodExecutor
!=
null
&&
this
.
target
!=
null
&&
this
.
target
.
equals
(
target
)
&&
this
.
argumentTypes
.
equals
(
argumentTypes
));
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录