Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
5c0f98ae
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,体验更适合开发者的 AI 搜索 >>
提交
5c0f98ae
编写于
5月 06, 2015
作者:
S
Sam Brannen
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Document & test AnnotatedElementUtils.getAllAnnotationAttributes
Issue: SPR-11514
上级
2015781e
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
78 addition
and
61 deletion
+78
-61
spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java
...pringframework/core/annotation/AnnotatedElementUtils.java
+59
-42
spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java
...framework/core/annotation/AnnotatedElementUtilsTests.java
+19
-19
未找到文件。
spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java
浏览文件 @
5c0f98ae
...
...
@@ -40,9 +40,12 @@ import org.springframework.util.MultiValueMap;
*/
public
class
AnnotatedElementUtils
{
private
static
final
Boolean
CONTINUE
=
null
;
/**
*
Get the fully qualified class names of all meta-annotation types
* <em>present</em> on the annotation (of the specified
*
<em>Get</em> the fully qualified class names of all meta-annotation
*
types
<em>present</em> on the annotation (of the specified
* {@code annotationType}) on the supplied {@link AnnotatedElement}.
*
* <p>This method finds all meta-annotations in the annotation hierarchy
...
...
@@ -63,8 +66,8 @@ public class AnnotatedElementUtils {
}
/**
*
Get the fully qualified class names of all meta-annotation types
* <em>present</em> on the annotation (of the specified
*
<em>Get</em> the fully qualified class names of all meta-annotation
*
types
<em>present</em> on the annotation (of the specified
* {@code annotationType}) on the supplied {@link AnnotatedElement}.
*
* <p>This method finds all meta-annotations in the annotation hierarchy
...
...
@@ -92,7 +95,7 @@ public class AnnotatedElementUtils {
@Override
public
Object
process
(
Annotation
annotation
,
int
metaDepth
)
{
types
.
add
(
annotation
.
annotationType
().
getName
());
return
null
;
return
CONTINUE
;
}
},
new
HashSet
<
AnnotatedElement
>(),
1
);
}
...
...
@@ -126,10 +129,7 @@ public class AnnotatedElementUtils {
@Override
public
Boolean
process
(
Annotation
annotation
,
int
metaDepth
)
{
boolean
found
=
annotation
.
annotationType
().
getName
().
equals
(
annotationType
);
if
(
found
&&
(
metaDepth
>
0
))
{
return
Boolean
.
TRUE
;
}
return
null
;
return
((
found
&&
(
metaDepth
>
0
))
?
Boolean
.
TRUE
:
CONTINUE
);
}
}));
}
...
...
@@ -155,7 +155,7 @@ public class AnnotatedElementUtils {
@Override
public
Boolean
process
(
Annotation
annotation
,
int
metaDepth
)
{
boolean
found
=
annotation
.
annotationType
().
getName
().
equals
(
annotationType
);
return
(
found
?
Boolean
.
TRUE
:
null
);
return
(
found
?
Boolean
.
TRUE
:
CONTINUE
);
}
}));
}
...
...
@@ -197,7 +197,7 @@ public class AnnotatedElementUtils {
*/
public
static
AnnotationAttributes
getAnnotationAttributes
(
AnnotatedElement
element
,
String
annotationType
,
boolean
classValuesAsString
,
boolean
nestedAnnotationsAsMap
)
{
return
processWithGetSemantics
(
element
,
annotationType
,
new
MergeAnnotationAttributesProcessor
(
annotationType
,
return
processWithGetSemantics
(
element
,
annotationType
,
new
Merge
d
AnnotationAttributesProcessor
(
annotationType
,
classValuesAsString
,
nestedAnnotationsAsMap
));
}
...
...
@@ -215,6 +215,7 @@ public class AnnotatedElementUtils {
* @param annotationType the annotation type to find; never {@code null}
* @return the merged {@code AnnotationAttributes}, or {@code null} if
* not found
* @since 4.2
*/
public
static
AnnotationAttributes
findAnnotationAttributes
(
AnnotatedElement
element
,
Class
<?
extends
Annotation
>
annotationType
)
{
...
...
@@ -237,6 +238,7 @@ public class AnnotatedElementUtils {
* type to find; never {@code null} or empty
* @return the merged {@code AnnotationAttributes}, or {@code null} if
* not found
* @since 4.2
*/
public
static
AnnotationAttributes
findAnnotationAttributes
(
AnnotatedElement
element
,
String
annotationType
)
{
return
findAnnotationAttributes
(
element
,
annotationType
,
false
,
false
);
...
...
@@ -262,6 +264,7 @@ public class AnnotatedElementUtils {
* as Annotation instances
* @return the merged {@code AnnotationAttributes}, or {@code null} if
* not found
* @since 4.2
*/
public
static
AnnotationAttributes
findAnnotationAttributes
(
AnnotatedElement
element
,
String
annotationType
,
boolean
classValuesAsString
,
boolean
nestedAnnotationsAsMap
)
{
...
...
@@ -292,28 +295,47 @@ public class AnnotatedElementUtils {
* as Annotation instances
* @return the merged {@code AnnotationAttributes}, or {@code null} if
* not found
* @since 4.2
*/
private
static
AnnotationAttributes
findAnnotationAttributes
(
AnnotatedElement
element
,
String
annotationType
,
boolean
searchOnInterfaces
,
boolean
searchOnSuperclasses
,
boolean
searchOnMethodsInInterfaces
,
boolean
searchOnMethodsInSuperclasses
,
boolean
classValuesAsString
,
boolean
nestedAnnotationsAsMap
)
{
return
processWithFindSemantics
(
element
,
annotationType
,
searchOnInterfaces
,
searchOnSuperclasses
,
searchOnMethodsInInterfaces
,
searchOnMethodsInSuperclasses
,
new
MergeAnnotationAttributesProcessor
(
searchOnMethodsInInterfaces
,
searchOnMethodsInSuperclasses
,
new
Merge
d
AnnotationAttributesProcessor
(
annotationType
,
classValuesAsString
,
nestedAnnotationsAsMap
));
}
/**
* <em>Get</em> the annotation attributes of <strong>all</strong> annotations
* of the specified {@code annotationType} in the annotation hierarchy above
* the supplied {@link AnnotatedElement} and store the results in a
* {@link MultiValueMap}.
*
* <p>Note: in contrast to {@link #getAnnotationAttributes(AnnotatedElement, String)},
* this method does <em>not</em> take attribute overrides into account.
*
* @param element the annotated element; never {@code null}
* @param annotationType the fully qualified class name of the annotation
* type to find; never {@code null} or empty
* @return a {@link MultiValueMap} containing the annotation attributes
* from all annotations found, or {@code null} if not found
* @return a {@link MultiValueMap} keyed by attribute name, containing
* the annotation attributes from all annotations found, or {@code null}
* if not found
* @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
public
static
MultiValueMap
<
String
,
Object
>
getAllAnnotationAttributes
(
AnnotatedElement
element
,
String
annotationType
)
{
return
getAllAnnotationAttributes
(
element
,
annotationType
,
false
,
false
);
}
/**
* <em>Get</em> the annotation attributes of <strong>all</strong> annotations
* of the specified {@code annotationType} in the annotation hierarchy above
* the supplied {@link AnnotatedElement} and store the results in a
* {@link MultiValueMap}.
*
* <p>Note: in contrast to {@link #getAnnotationAttributes(AnnotatedElement, String)},
* this method does <em>not</em> take attribute overrides into account.
*
* @param element the annotated element; never {@code null}
* @param annotationType the fully qualified class name of the annotation
* type to find; never {@code null} or empty
...
...
@@ -322,39 +344,34 @@ public class AnnotatedElementUtils {
* @param nestedAnnotationsAsMap whether to convert nested Annotation
* instances into {@link AnnotationAttributes} maps or to preserve them
* as Annotation instances
* @return a {@link MultiValueMap} containing the annotation attributes
* from all annotations found, or {@code null} if not found
* @return a {@link MultiValueMap} keyed by attribute name, containing
* the annotation attributes from all annotations found, or {@code null}
* if not found
*/
public
static
MultiValueMap
<
String
,
Object
>
getAllAnnotationAttributes
(
AnnotatedElement
element
,
final
String
annotationType
,
final
boolean
classValuesAsString
,
final
boolean
nestedAnnotationsAsMap
)
{
final
MultiValueMap
<
String
,
Object
>
attributes
=
new
LinkedMultiValueMap
<
String
,
Object
>();
final
MultiValueMap
<
String
,
Object
>
attributesMap
=
new
LinkedMultiValueMap
<
String
,
Object
>();
processWithGetSemantics
(
element
,
annotationType
,
new
SimpleAnnotationProcessor
<
Void
>()
{
processWithGetSemantics
(
element
,
annotationType
,
new
Processor
<
Void
>()
{
@Override
public
Void
process
(
Annotation
annotation
,
int
metaDepth
)
{
if
(
annotation
.
annotationType
().
getName
().
equals
(
annotationType
))
{
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
AnnotationUtils
.
getAnnotationAttributes
(
annotation
,
classValuesAsString
,
nestedAnnotationsAsMap
).
entrySet
())
{
attributes
.
add
(
entry
.
getKey
(),
entry
.
getValue
());
boolean
found
=
annotation
.
annotationType
().
getName
().
equals
(
annotationType
);
if
(
found
)
{
AnnotationAttributes
annotationAttributes
=
AnnotationUtils
.
getAnnotationAttributes
(
annotation
,
classValuesAsString
,
nestedAnnotationsAsMap
);
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
annotationAttributes
.
entrySet
())
{
attributesMap
.
add
(
entry
.
getKey
(),
entry
.
getValue
());
}
}
// Continue searching...
return
null
;
}
@Override
public
void
postProcess
(
Annotation
annotation
,
Void
result
)
{
for
(
String
key
:
attributes
.
keySet
())
{
if
(!
AnnotationUtils
.
VALUE
.
equals
(
key
))
{
Object
value
=
AnnotationUtils
.
getValue
(
annotation
,
key
);
if
(
value
!=
null
)
{
attributes
.
add
(
key
,
value
);
}
}
}
}
});
return
(
attributes
.
isEmpty
()
?
null
:
attributes
);
return
(
attributes
Map
.
isEmpty
()
?
null
:
attributesMap
);
}
/**
...
...
@@ -725,8 +742,8 @@ public class AnnotatedElementUtils {
}
/**
* {@link Processor} that
only
{@linkplain #process processes} annotations
*
and
does not {@link #postProcess} results.
* {@link Processor} that {@linkplain #process processes} annotations
*
but
does not {@link #postProcess} results.
* @since 4.2
*/
private
abstract
static
class
SimpleAnnotationProcessor
<
T
>
implements
Processor
<
T
>
{
...
...
@@ -748,14 +765,14 @@ public class AnnotatedElementUtils {
* @see AnnotationUtils#getAnnotationAttributes(Annotation)
* @since 4.2
*/
private
static
class
MergeAnnotationAttributesProcessor
implements
Processor
<
AnnotationAttributes
>
{
private
static
class
Merge
d
AnnotationAttributesProcessor
implements
Processor
<
AnnotationAttributes
>
{
private
final
String
annotationType
;
private
final
boolean
classValuesAsString
;
private
final
boolean
nestedAnnotationsAsMap
;
MergeAnnotationAttributesProcessor
(
String
annotationType
,
boolean
classValuesAsString
,
boolean
nestedAnnotationsAsMap
)
{
Merge
d
AnnotationAttributesProcessor
(
String
annotationType
,
boolean
classValuesAsString
,
boolean
nestedAnnotationsAsMap
)
{
this
.
annotationType
=
annotationType
;
this
.
classValuesAsString
=
classValuesAsString
;
this
.
nestedAnnotationsAsMap
=
nestedAnnotationsAsMap
;
...
...
@@ -764,16 +781,16 @@ public class AnnotatedElementUtils {
@Override
public
AnnotationAttributes
process
(
Annotation
annotation
,
int
metaDepth
)
{
boolean
found
=
annotation
.
annotationType
().
getName
().
equals
(
annotationType
);
return
(
!
found
?
null
:
AnnotationUtils
.
getAnnotationAttributes
(
annotation
,
classValuesAsString
,
nestedAnnotationsAsMap
)
);
return
(
found
?
AnnotationUtils
.
getAnnotationAttributes
(
annotation
,
classValuesAsString
,
nestedAnnotationsAsMap
)
:
null
);
}
@Override
public
void
postProcess
(
Annotation
annotation
,
AnnotationAttributes
result
)
{
for
(
String
key
:
result
.
keySet
())
{
public
void
postProcess
(
Annotation
annotation
,
AnnotationAttributes
attributes
)
{
for
(
String
key
:
attributes
.
keySet
())
{
if
(!
AnnotationUtils
.
VALUE
.
equals
(
key
))
{
Object
value
=
AnnotationUtils
.
getValue
(
annotation
,
key
);
if
(
value
!=
null
)
{
result
.
put
(
key
,
AnnotationUtils
.
adaptValue
(
value
,
classValuesAsString
,
nestedAnnotationsAsMap
));
attributes
.
put
(
key
,
AnnotationUtils
.
adaptValue
(
value
,
classValuesAsString
,
nestedAnnotationsAsMap
));
}
}
}
...
...
spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java
浏览文件 @
5c0f98ae
...
...
@@ -118,14 +118,26 @@ public class AnnotatedElementUtilsTests {
assertTrue
(
isAnnotated
(
ComposedTransactionalComponentClass
.
class
,
ComposedTransactionalComponent
.
class
.
getName
()));
}
@Test
public
void
getAllAnnotationAttributesOnNonAnnotatedClass
()
{
assertNull
(
getAllAnnotationAttributes
(
NonAnnotatedClass
.
class
,
Transactional
.
class
.
getName
()));
}
@Test
public
void
getAllAnnotationAttributesOnClassWithLocalAnnotation
()
{
MultiValueMap
<
String
,
Object
>
attributes
=
getAllAnnotationAttributes
(
TxConfig
.
class
,
Transactional
.
class
.
getName
());
MultiValueMap
<
String
,
Object
>
attributes
=
getAllAnnotationAttributes
(
TxConfig
.
class
,
Transactional
.
class
.
getName
());
assertNotNull
(
"Annotation attributes map for @Transactional on TxConfig"
,
attributes
);
assertEquals
(
"value for TxConfig."
,
Arrays
.
asList
(
"TxConfig"
),
attributes
.
get
(
"value"
));
}
@Test
public
void
getAllAnnotationAttributesFavorsInheritedComposedAnnotationsOverMoreLocallyDeclaredComposedAnnotations
()
{
MultiValueMap
<
String
,
Object
>
attributes
=
getAllAnnotationAttributes
(
SubSubClassWithInheritedComposedAnnotation
.
class
,
Transactional
.
class
.
getName
());
assertNotNull
(
"Annotation attributes map for @Transactional on SubSubClassWithInheritedComposedAnnotation"
,
attributes
);
assertEquals
(
Arrays
.
asList
(
"composed1"
),
attributes
.
get
(
"qualifier"
));
}
/**
* If the "value" entry contains both "DerivedTxConfig" AND "TxConfig", then
* the algorithm is accidentally picking up shadowed annotations of the same
...
...
@@ -133,12 +145,11 @@ public class AnnotatedElementUtilsTests {
* logic in {@link org.springframework.context.annotation.ProfileCondition}
* to fail.
*
* @see org.springframework.core.env.EnvironmentIntegrationTests#mostSpecificDerivedClassDrivesEnvironment_withDevEnvAndDerivedDevConfigClass
* @see org.springframework.core.env.Environment
System
IntegrationTests#mostSpecificDerivedClassDrivesEnvironment_withDevEnvAndDerivedDevConfigClass
*/
@Test
public
void
getAllAnnotationAttributesOnClassWithLocalAnnotationThatShadowsAnnotationFromSuperclass
()
{
MultiValueMap
<
String
,
Object
>
attributes
=
getAllAnnotationAttributes
(
DerivedTxConfig
.
class
,
Transactional
.
class
.
getName
());
MultiValueMap
<
String
,
Object
>
attributes
=
getAllAnnotationAttributes
(
DerivedTxConfig
.
class
,
Transactional
.
class
.
getName
());
assertNotNull
(
"Annotation attributes map for @Transactional on DerivedTxConfig"
,
attributes
);
assertEquals
(
"value for DerivedTxConfig."
,
Arrays
.
asList
(
"DerivedTxConfig"
),
attributes
.
get
(
"value"
));
}
...
...
@@ -146,7 +157,7 @@ public class AnnotatedElementUtilsTests {
/**
* Note: this functionality is required by {@link org.springframework.context.annotation.ProfileCondition}.
*
* @see org.springframework.core.env.EnvironmentIntegrationTests
* @see org.springframework.core.env.Environment
System
IntegrationTests
*/
@Test
public
void
getAllAnnotationAttributesOnClassWithMultipleComposedAnnotations
()
{
...
...
@@ -211,7 +222,6 @@ public class AnnotatedElementUtilsTests {
assertNotNull
(
"Should find @Transactional on ConcreteClassWithInheritedAnnotation"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
getAnnotationAttributesOnInheritedAnnotationInterface
()
{
String
name
=
Transactional
.
class
.
getName
();
...
...
@@ -219,56 +229,48 @@ public class AnnotatedElementUtilsTests {
assertNotNull
(
"Should get @Transactional on InheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesOnInheritedAnnotationInterface
()
{
AnnotationAttributes
attributes
=
findAnnotationAttributes
(
InheritedAnnotationInterface
.
class
,
Transactional
.
class
);
assertNotNull
(
"Should find @Transactional on InheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesOnSubInheritedAnnotationInterface
()
{
AnnotationAttributes
attributes
=
findAnnotationAttributes
(
SubInheritedAnnotationInterface
.
class
,
Transactional
.
class
);
assertNotNull
(
"Should find @Transactional on SubInheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesOnSubSubInheritedAnnotationInterface
()
{
AnnotationAttributes
attributes
=
findAnnotationAttributes
(
SubSubInheritedAnnotationInterface
.
class
,
Transactional
.
class
);
assertNotNull
(
"Should find @Transactional on SubSubInheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesOnNonInheritedAnnotationInterface
()
{
AnnotationAttributes
attributes
=
findAnnotationAttributes
(
NonInheritedAnnotationInterface
.
class
,
Order
.
class
);
assertNotNull
(
"Should find @Order on NonInheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
getAnnotationAttributesOnNonInheritedAnnotationInterface
()
{
AnnotationAttributes
attributes
=
getAnnotationAttributes
(
NonInheritedAnnotationInterface
.
class
,
Order
.
class
.
getName
());
assertNotNull
(
"Should get @Order on NonInheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesOnSubNonInheritedAnnotationInterface
()
{
AnnotationAttributes
attributes
=
findAnnotationAttributes
(
SubNonInheritedAnnotationInterface
.
class
,
Order
.
class
);
assertNotNull
(
"Should find @Order on SubNonInheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesOnSubSubNonInheritedAnnotationInterface
()
{
AnnotationAttributes
attributes
=
findAnnotationAttributes
(
SubSubNonInheritedAnnotationInterface
.
class
,
Order
.
class
);
assertNotNull
(
"Should find @Order on SubSubNonInheritedAnnotationInterface"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesInheritedFromInterfaceMethod
()
throws
NoSuchMethodException
{
Method
method
=
ConcreteClassWithInheritedAnnotation
.
class
.
getMethod
(
"handleFromInterface"
);
...
...
@@ -276,7 +278,6 @@ public class AnnotatedElementUtilsTests {
assertNotNull
(
"Should find @Order on ConcreteClassWithInheritedAnnotation.handleFromInterface() method"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesInheritedFromAbstractMethod
()
throws
NoSuchMethodException
{
Method
method
=
ConcreteClassWithInheritedAnnotation
.
class
.
getMethod
(
"handle"
);
...
...
@@ -328,7 +329,6 @@ public class AnnotatedElementUtilsTests {
assertNotNull
(
"Should find @Order on StringGenericParameter.getFor() bridge method"
,
attributes
);
}
/** @since 4.2 */
@Test
public
void
findAnnotationAttributesOnClassWithMetaAndLocalTxConfig
()
{
AnnotationAttributes
attributes
=
findAnnotationAttributes
(
MetaAndLocalTxConfigClass
.
class
,
Transactional
.
class
);
...
...
@@ -379,7 +379,7 @@ public class AnnotatedElementUtilsTests {
boolean
readOnly
()
default
false
;
}
@Transactional
@Transactional
(
qualifier
=
"composed1"
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
TYPE
)
@Documented
...
...
@@ -387,7 +387,7 @@ public class AnnotatedElementUtilsTests {
@interface
Composed1
{
}
@Transactional
(
readOnly
=
true
)
@Transactional
(
qualifier
=
"composed2"
,
readOnly
=
true
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
TYPE
)
@Documented
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录