Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
7fbc20e2
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,发现更多精彩内容 >>
提交
7fbc20e2
编写于
4月 11, 2017
作者:
J
Juergen Hoeller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Undeprecate TypeVariableMap methods on GenericTypeResolver
Issue: SPR-15429
上级
42420a2d
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
148 addition
and
1 deletion
+148
-1
spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java
...in/java/org/springframework/core/GenericTypeResolver.java
+85
-0
spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
...va/org/springframework/core/GenericTypeResolverTests.java
+63
-1
未找到文件。
spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java
浏览文件 @
7fbc20e2
...
...
@@ -21,8 +21,12 @@ import java.lang.reflect.ParameterizedType;
import
java.lang.reflect.Type
;
import
java.lang.reflect.TypeVariable
;
import
java.lang.reflect.WildcardType
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ConcurrentReferenceHashMap
;
/**
* Helper class for resolving generic types against type variables.
...
...
@@ -38,6 +42,11 @@ import org.springframework.util.Assert;
*/
public
abstract
class
GenericTypeResolver
{
/** Cache from Class to TypeVariable Map */
@SuppressWarnings
(
"rawtypes"
)
private
static
final
Map
<
Class
<?>,
Map
<
TypeVariable
,
Type
>>
typeVariableCache
=
new
ConcurrentReferenceHashMap
<>();
/**
* Determine the target type for the given generic parameter type.
* @param methodParameter the method parameter specification
...
...
@@ -196,4 +205,80 @@ public abstract class GenericTypeResolver {
return
ResolvableType
.
NONE
;
}
/**
* Resolve the specified generic type against the given TypeVariable map.
* <p>Used by Spring Data.
* @param genericType the generic type to resolve
* @param map the TypeVariable Map to resolved against
* @return the type if it resolves to a Class, or {@code Object.class} otherwise
*/
@SuppressWarnings
(
"rawtypes"
)
public
static
Class
<?>
resolveType
(
Type
genericType
,
Map
<
TypeVariable
,
Type
>
map
)
{
return
ResolvableType
.
forType
(
genericType
,
new
TypeVariableMapVariableResolver
(
map
)).
resolve
(
Object
.
class
);
}
/**
* Build a mapping of {@link TypeVariable#getName TypeVariable names} to
* {@link Class concrete classes} for the specified {@link Class}.
* Searches all super types, enclosing types and interfaces.
* @see #resolveType(Type, Map)
*/
@SuppressWarnings
(
"rawtypes"
)
public
static
Map
<
TypeVariable
,
Type
>
getTypeVariableMap
(
Class
<?>
clazz
)
{
Map
<
TypeVariable
,
Type
>
typeVariableMap
=
typeVariableCache
.
get
(
clazz
);
if
(
typeVariableMap
==
null
)
{
typeVariableMap
=
new
HashMap
<>();
buildTypeVariableMap
(
ResolvableType
.
forClass
(
clazz
),
typeVariableMap
);
typeVariableCache
.
put
(
clazz
,
Collections
.
unmodifiableMap
(
typeVariableMap
));
}
return
typeVariableMap
;
}
@SuppressWarnings
(
"rawtypes"
)
private
static
void
buildTypeVariableMap
(
ResolvableType
type
,
Map
<
TypeVariable
,
Type
>
typeVariableMap
)
{
if
(
type
!=
ResolvableType
.
NONE
)
{
if
(
type
.
getType
()
instanceof
ParameterizedType
)
{
TypeVariable
<?>[]
variables
=
type
.
resolve
().
getTypeParameters
();
for
(
int
i
=
0
;
i
<
variables
.
length
;
i
++)
{
ResolvableType
generic
=
type
.
getGeneric
(
i
);
while
(
generic
.
getType
()
instanceof
TypeVariable
<?>)
{
generic
=
generic
.
resolveType
();
}
if
(
generic
!=
ResolvableType
.
NONE
)
{
typeVariableMap
.
put
(
variables
[
i
],
generic
.
getType
());
}
}
}
buildTypeVariableMap
(
type
.
getSuperType
(),
typeVariableMap
);
for
(
ResolvableType
interfaceType
:
type
.
getInterfaces
())
{
buildTypeVariableMap
(
interfaceType
,
typeVariableMap
);
}
if
(
type
.
resolve
().
isMemberClass
())
{
buildTypeVariableMap
(
ResolvableType
.
forClass
(
type
.
resolve
().
getEnclosingClass
()),
typeVariableMap
);
}
}
}
@SuppressWarnings
({
"serial"
,
"rawtypes"
})
private
static
class
TypeVariableMapVariableResolver
implements
ResolvableType
.
VariableResolver
{
private
final
Map
<
TypeVariable
,
Type
>
typeVariableMap
;
public
TypeVariableMapVariableResolver
(
Map
<
TypeVariable
,
Type
>
typeVariableMap
)
{
this
.
typeVariableMap
=
typeVariableMap
;
}
@Override
public
ResolvableType
resolveVariable
(
TypeVariable
<?>
variable
)
{
Type
type
=
this
.
typeVariableMap
.
get
(
variable
);
return
(
type
!=
null
?
ResolvableType
.
forType
(
type
)
:
null
);
}
@Override
public
Object
getSource
()
{
return
this
.
typeVariableMap
;
}
}
}
spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
浏览文件 @
7fbc20e2
...
...
@@ -17,7 +17,11 @@
package
org.springframework.core
;
import
java.io.Serializable
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Type
;
import
java.lang.reflect.TypeVariable
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -32,7 +36,7 @@ import static org.springframework.util.ReflectionUtils.*;
* @author Juergen Hoeller
* @author Sam Brannen
*/
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
public
class
GenericTypeResolverTests
{
@Test
...
...
@@ -72,11 +76,69 @@ public class GenericTypeResolverTests {
resolveReturnTypeArgument
(
findMethod
(
MyTypeWithMethods
.
class
,
"object"
),
MyInterfaceType
.
class
));
}
@Test
public
void
testResolveType
()
{
Method
intMessageMethod
=
findMethod
(
MyTypeWithMethods
.
class
,
"readIntegerInputMessage"
,
MyInterfaceType
.
class
);
MethodParameter
intMessageMethodParam
=
new
MethodParameter
(
intMessageMethod
,
0
);
assertEquals
(
MyInterfaceType
.
class
,
resolveType
(
intMessageMethodParam
.
getGenericParameterType
(),
new
HashMap
<>()));
Method
intArrMessageMethod
=
findMethod
(
MyTypeWithMethods
.
class
,
"readIntegerArrayInputMessage"
,
MyInterfaceType
[].
class
);
MethodParameter
intArrMessageMethodParam
=
new
MethodParameter
(
intArrMessageMethod
,
0
);
assertEquals
(
MyInterfaceType
[].
class
,
resolveType
(
intArrMessageMethodParam
.
getGenericParameterType
(),
new
HashMap
<>()));
Method
genericArrMessageMethod
=
findMethod
(
MySimpleTypeWithMethods
.
class
,
"readGenericArrayInputMessage"
,
Object
[].
class
);
MethodParameter
genericArrMessageMethodParam
=
new
MethodParameter
(
genericArrMessageMethod
,
0
);
Map
<
TypeVariable
,
Type
>
varMap
=
getTypeVariableMap
(
MySimpleTypeWithMethods
.
class
);
assertEquals
(
Integer
[].
class
,
resolveType
(
genericArrMessageMethodParam
.
getGenericParameterType
(),
varMap
));
}
@Test
public
void
testBoundParameterizedType
()
{
assertEquals
(
B
.
class
,
resolveTypeArgument
(
TestImpl
.
class
,
TestIfc
.
class
));
}
@Test
public
void
testGetTypeVariableMap
()
throws
Exception
{
Map
<
TypeVariable
,
Type
>
map
;
map
=
GenericTypeResolver
.
getTypeVariableMap
(
MySimpleInterfaceType
.
class
);
assertThat
(
map
.
toString
(),
equalTo
(
"{T=class java.lang.String}"
));
map
=
GenericTypeResolver
.
getTypeVariableMap
(
MyCollectionInterfaceType
.
class
);
assertThat
(
map
.
toString
(),
equalTo
(
"{T=java.util.Collection<java.lang.String>}"
));
map
=
GenericTypeResolver
.
getTypeVariableMap
(
MyCollectionSuperclassType
.
class
);
assertThat
(
map
.
toString
(),
equalTo
(
"{T=java.util.Collection<java.lang.String>}"
));
map
=
GenericTypeResolver
.
getTypeVariableMap
(
MySimpleTypeWithMethods
.
class
);
assertThat
(
map
.
toString
(),
equalTo
(
"{T=class java.lang.Integer}"
));
map
=
GenericTypeResolver
.
getTypeVariableMap
(
TopLevelClass
.
class
);
assertThat
(
map
.
toString
(),
equalTo
(
"{}"
));
map
=
GenericTypeResolver
.
getTypeVariableMap
(
TypedTopLevelClass
.
class
);
assertThat
(
map
.
toString
(),
equalTo
(
"{T=class java.lang.Integer}"
));
map
=
GenericTypeResolver
.
getTypeVariableMap
(
TypedTopLevelClass
.
TypedNested
.
class
);
assertThat
(
map
.
size
(),
equalTo
(
2
));
Type
t
=
null
;
Type
x
=
null
;
for
(
Map
.
Entry
<
TypeVariable
,
Type
>
entry
:
map
.
entrySet
())
{
if
(
entry
.
getKey
().
toString
().
equals
(
"T"
))
{
t
=
entry
.
getValue
();
}
else
{
x
=
entry
.
getValue
();
}
}
assertThat
(
t
,
equalTo
((
Type
)
Integer
.
class
));
assertThat
(
x
,
equalTo
((
Type
)
Long
.
class
));
}
@Test
public
void
getGenericsCannotBeResolved
()
throws
Exception
{
// SPR-11030
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录