Skip to content

Commit e25f1cb

Browse files
committed
Infer AnnotationAttributes method return types
- Drop 'expectedType' parameter from #getClass and #getEnum methods and rely on compiler inference based on type of assigned variable, e.g. public @interface Example { Color color(); Class<? extends UserType> userType(); int order() default 0; } AnnotationAttributes example = AnnotationUtils.getAnnotationAttributes(Example.class, true, true); Color color = example.getEnum("color"); Class<? extends UserType> userType = example.getClass("userType"); or in cases where there is no variable assignment (and thus no inference possible), use explicit generic type, e.g. bean.setColor(example.<Color>getEnum("color")); - Rename #get{Int=>Number} and update return type from int to <N extends Number>, allowing invocations such as: int order = example.getNumber("order"); These changes reduce the overall number of methods exposed by AnnotationAttributes, while at the same time providing comprehensive access to all possible annotation attribute types -- that is, instead of requiring explicit #getInt, #getFloat, #getDouble methods, the single #getNumber method is capabable of handling them all, and without any casting required. And the obvious additional benefit is more concise invocation as no redundant 'expectedType' parameters are required.
1 parent 997c6c5 commit e25f1cb

File tree

13 files changed

+43
-45
lines changed

13 files changed

+43
-45
lines changed

org.springframework.context/src/main/java/org/springframework/cache/annotation/ProxyCachingConfiguration.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {
4444
new BeanFactoryCacheOperationSourceAdvisor();
4545
advisor.setCacheOperationSource(cacheOperationSource());
4646
advisor.setAdvice(cacheInterceptor());
47-
advisor.setOrder(this.enableCaching.getInt("order"));
47+
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
4848
return advisor;
4949
}
5050

org.springframework.context/src/main/java/org/springframework/context/annotation/AdviceModeImportSelector.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
7373
"@%s is not present on importing class '%s' as expected",
7474
annoType.getSimpleName(), importingClassMetadata.getClassName()));
7575

76-
AdviceMode adviceMode =
77-
attributes.getEnum(this.getAdviceModeAttributeName(), AdviceMode.class);
76+
AdviceMode adviceMode = attributes.getEnum(this.getAdviceModeAttributeName());
7877

7978
String[] imports = selectImports(adviceMode);
8079
Assert.notNull(imports, String.format("Unknown AdviceMode: '%s'", adviceMode));

org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,8 @@ static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
232232
}
233233
if (abd instanceof AbstractBeanDefinition) {
234234
if (metadata.isAnnotated(Role.class.getName())) {
235-
((AbstractBeanDefinition)abd).setRole(
236-
attributesFor(metadata, Role.class).getInt("value"));
235+
int role = attributesFor(metadata, Role.class).getNumber("value");
236+
((AbstractBeanDefinition)abd).setRole(role);
237237
}
238238
}
239239
}

org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationScopeMetadataResolver.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
8181
attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
8282
if (attributes != null) {
8383
metadata.setScopeName(attributes.getString("value"));
84-
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode", ScopedProxyMode.class);
84+
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
8585
if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
8686
proxyMode = this.defaultProxyMode;
8787
}

org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,15 @@ public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan) {
7070
Assert.notNull(this.resourceLoader, "ResourceLoader must not be null");
7171
scanner.setResourceLoader(this.resourceLoader);
7272

73-
scanner.setBeanNameGenerator(BeanUtils.instantiateClass(
74-
componentScan.getClass("nameGenerator", BeanNameGenerator.class)));
73+
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
74+
scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
7575

76-
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy", ScopedProxyMode.class);
76+
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
7777
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
7878
scanner.setScopedProxyMode(scopedProxyMode);
7979
} else {
80-
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(
81-
componentScan.getClass("scopeResolver", ScopeMetadataResolver.class)));
80+
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
81+
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
8282
}
8383

8484
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
@@ -118,7 +118,7 @@ public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan) {
118118

119119
private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
120120
List<TypeFilter> typeFilters = new ArrayList<TypeFilter>();
121-
FilterType filterType = filterAttributes.getEnum("type", FilterType.class);
121+
FilterType filterType = filterAttributes.getEnum("type");
122122

123123
for (Class<?> filterClass : filterAttributes.getClassArray("value")) {
124124
switch (filterType) {

org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
198198
// consider role
199199
AnnotationAttributes role = attributesFor(metadata, Role.class);
200200
if (role != null) {
201-
beanDef.setRole(role.getInt("value"));
201+
beanDef.setRole(role.<Integer>getNumber("value"));
202202
}
203203

204204
// consider name and any aliases
@@ -246,7 +246,7 @@ else if (configClass.getMetadata().isAnnotated(Lazy.class.getName())){
246246
}
247247
}
248248

249-
Autowire autowire = bean.getEnum("autowire", Autowire.class);
249+
Autowire autowire = bean.getEnum("autowire");
250250
if (autowire.isAutowire()) {
251251
beanDef.setAutowireMode(autowire.value());
252252
}
@@ -266,7 +266,7 @@ else if (configClass.getMetadata().isAnnotated(Lazy.class.getName())){
266266
AnnotationAttributes scope = attributesFor(metadata, Scope.class);
267267
if (scope != null) {
268268
beanDef.setScope(scope.getString("value"));
269-
proxyMode = scope.getEnum("proxyMode", ScopedProxyMode.class);
269+
proxyMode = scope.getEnum("proxyMode");
270270
if (proxyMode == ScopedProxyMode.DEFAULT) {
271271
proxyMode = ScopedProxyMode.NO;
272272
}

org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,7 @@ protected void doProcessConfigurationClass(ConfigurationClass configClass, Annot
216216
if (metadata.isAnnotated(ImportResource.class.getName())) {
217217
AnnotationAttributes importResource = attributesFor(metadata, ImportResource.class);
218218
String[] resources = importResource.getStringArray("value");
219-
Class<? extends BeanDefinitionReader> readerClass =
220-
importResource.getClass("reader", BeanDefinitionReader.class);
219+
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
221220
for (String resource : resources) {
222221
configClass.addImportedResource(resource, readerClass);
223222
}

org.springframework.context/src/main/java/org/springframework/context/annotation/LoadTimeWeavingConfiguration.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
import static org.springframework.context.weaving.AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE;
2020

21-
import java.util.Map;
22-
2321
import org.springframework.beans.factory.BeanClassLoaderAware;
2422
import org.springframework.beans.factory.annotation.Autowired;
2523
import org.springframework.beans.factory.config.BeanDefinition;
@@ -80,7 +78,8 @@ public LoadTimeWeaver loadTimeWeaver() {
8078
loadTimeWeaver = new DefaultContextLoadTimeWeaver(this.beanClassLoader);
8179
}
8280

83-
switch (this.enableLTW.getEnum("aspectjWeaving", AspectJWeaving.class)) {
81+
AspectJWeaving aspectJWeaving = this.enableLTW.getEnum("aspectjWeaving");
82+
switch (aspectJWeaving) {
8483
case DISABLED:
8584
// AJ weaving is disabled -> do nothing
8685
break;

org.springframework.context/src/main/java/org/springframework/scheduling/annotation/ProxyAsyncConfiguration.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
4646

4747
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
4848

49-
Class<? extends Annotation> customAsyncAnnotation = enableAsync.getClass("annotation", Annotation.class);
49+
Class<? extends Annotation> customAsyncAnnotation = enableAsync.getClass("annotation");
5050
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
5151
bpp.setAsyncAnnotationType(customAsyncAnnotation);
5252
}
@@ -56,8 +56,7 @@ public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
5656
}
5757

5858
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
59-
60-
bpp.setOrder(this.enableAsync.getInt("order"));
59+
bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
6160

6261
return bpp;
6362
}

org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationAttributes.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,18 @@ public boolean getBoolean(String attributeName) {
9292
return doGet(attributeName, Boolean.class);
9393
}
9494

95-
public int getInt(String attributeName) {
96-
return doGet(attributeName, Integer.class);
95+
@SuppressWarnings("unchecked")
96+
public <N extends Number> N getNumber(String attributeName) {
97+
return (N) doGet(attributeName, Integer.class);
9798
}
9899

99-
public <E extends Enum<?>> E getEnum(String attributeName, Class<E> enumType) {
100-
return doGet(attributeName, enumType);
100+
@SuppressWarnings("unchecked")
101+
public <E extends Enum<?>> E getEnum(String attributeName) {
102+
return (E) doGet(attributeName, Enum.class);
101103
}
102104

103105
@SuppressWarnings("unchecked")
104-
public <T> Class<? extends T> getClass(String attributeName, Class<T> expectedType) {
106+
public <T> Class<? extends T> getClass(String attributeName) {
105107
return (Class<T>)doGet(attributeName, Class.class);
106108
}
107109

org.springframework.core/src/test/java/org/springframework/core/annotation/AnnotationAttributesTests.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ public void testTypeSafeAttributeAccess() {
5555
assertThat(a.getStringArray("names"), equalTo(new String[] { "dave", "frank", "hal" }));
5656
assertThat(a.getBoolean("bool1"), equalTo(true));
5757
assertThat(a.getBoolean("bool2"), equalTo(false));
58-
assertThat(a.getEnum("color", Color.class), equalTo(Color.RED));
59-
assertTrue(a.getClass("clazz", Number.class).equals(Integer.class));
58+
assertThat(a.<Color>getEnum("color"), equalTo(Color.RED));
59+
assertTrue(a.getClass("clazz").equals(Integer.class));
6060
assertThat(a.getClassArray("classes"), equalTo(new Class[] { Number.class, Short.class, Integer.class }));
61-
assertThat(a.getInt("number"), equalTo(42));
62-
assertThat(a.getAnnotation("anno").getInt("value"), equalTo(10));
61+
assertThat(a.<Integer>getNumber("number"), equalTo(42));
62+
assertThat(a.getAnnotation("anno").<Integer>getNumber("value"), equalTo(10));
6363
assertThat(a.getAnnotationArray("annoArray")[0].getString("name"), equalTo("algernon"));
6464
}
6565

@@ -68,13 +68,13 @@ public void getEnum_emptyAttributeName() {
6868
AnnotationAttributes a = new AnnotationAttributes();
6969
a.put("color", "RED");
7070
try {
71-
a.getEnum("", Color.class);
71+
a.getEnum("");
7272
fail();
7373
} catch (IllegalArgumentException ex) {
7474
assertThat(ex.getMessage(), equalTo("attributeName must not be null or empty"));
7575
}
7676
try {
77-
a.getEnum(null, Color.class);
77+
a.getEnum(null);
7878
fail();
7979
} catch (IllegalArgumentException ex) {
8080
assertThat(ex.getMessage(), equalTo("attributeName must not be null or empty"));
@@ -86,7 +86,7 @@ public void getEnum_notFound() {
8686
AnnotationAttributes a = new AnnotationAttributes();
8787
a.put("color", "RED");
8888
try {
89-
a.getEnum("colour", Color.class);
89+
a.getEnum("colour");
9090
fail();
9191
} catch (IllegalArgumentException ex) {
9292
assertThat(ex.getMessage(), equalTo("Attribute 'colour' not found"));
@@ -98,11 +98,11 @@ public void getEnum_typeMismatch() {
9898
AnnotationAttributes a = new AnnotationAttributes();
9999
a.put("color", "RED");
100100
try {
101-
a.getEnum("color", Color.class);
101+
a.getEnum("color");
102102
fail();
103103
} catch (IllegalArgumentException ex) {
104104
String expected =
105-
"Attribute 'color' is of type [String], but [Color] was expected";
105+
"Attribute 'color' is of type [String], but [Enum] was expected";
106106
assertThat(ex.getMessage().substring(0, expected.length()), equalTo(expected));
107107
}
108108
}

org.springframework.core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -109,34 +109,34 @@ private void doTestAnnotationInfo(AnnotationMetadata metadata) {
109109
{ // perform tests with classValuesAsString = false (the default)
110110
AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName());
111111
assertThat(specialAttrs.size(), is(6));
112-
assertTrue(String.class.isAssignableFrom(specialAttrs.getClass("clazz", Object.class)));
113-
assertThat(specialAttrs.getEnum("state", Thread.State.class), is(Thread.State.NEW));
112+
assertTrue(String.class.isAssignableFrom(specialAttrs.getClass("clazz")));
113+
assertTrue(specialAttrs.getEnum("state").equals(Thread.State.NEW));
114114

115115
AnnotationAttributes nestedAnno = specialAttrs.getAnnotation("nestedAnno");
116116
assertThat("na", is(nestedAnno.getString("value")));
117-
assertThat(nestedAnno.getEnum("anEnum", SomeEnum.class), is(SomeEnum.LABEL1));
117+
assertTrue(nestedAnno.getEnum("anEnum").equals(SomeEnum.LABEL1));
118118
assertArrayEquals(new Class[]{String.class}, (Class[])nestedAnno.get("classArray"));
119119

120120
AnnotationAttributes[] nestedAnnoArray = specialAttrs.getAnnotationArray("nestedAnnoArray");
121121
assertThat(nestedAnnoArray.length, is(2));
122122
assertThat(nestedAnnoArray[0].getString("value"), is("default"));
123-
assertThat(nestedAnnoArray[0].getEnum("anEnum", SomeEnum.class), is(SomeEnum.DEFAULT));
123+
assertTrue(nestedAnnoArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT));
124124
assertArrayEquals(new Class[]{Void.class}, (Class[])nestedAnnoArray[0].get("classArray"));
125125
assertThat(nestedAnnoArray[1].getString("value"), is("na1"));
126-
assertThat(nestedAnnoArray[1].getEnum("anEnum", SomeEnum.class), is(SomeEnum.LABEL2));
126+
assertTrue(nestedAnnoArray[1].getEnum("anEnum").equals(SomeEnum.LABEL2));
127127
assertArrayEquals(new Class[]{Number.class}, (Class[])nestedAnnoArray[1].get("classArray"));
128128
assertArrayEquals(new Class[]{Number.class}, nestedAnnoArray[1].getClassArray("classArray"));
129129

130130
AnnotationAttributes optional = specialAttrs.getAnnotation("optional");
131131
assertThat(optional.getString("value"), is("optional"));
132-
assertThat(optional.getEnum("anEnum", SomeEnum.class), is(SomeEnum.DEFAULT));
132+
assertTrue(optional.getEnum("anEnum").equals(SomeEnum.DEFAULT));
133133
assertArrayEquals(new Class[]{Void.class}, (Class[])optional.get("classArray"));
134134
assertArrayEquals(new Class[]{Void.class}, optional.getClassArray("classArray"));
135135

136136
AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray");
137137
assertThat(optionalArray.length, is(1));
138138
assertThat(optionalArray[0].getString("value"), is("optional"));
139-
assertThat(optionalArray[0].getEnum("anEnum", SomeEnum.class), is(SomeEnum.DEFAULT));
139+
assertTrue(optionalArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT));
140140
assertArrayEquals(new Class[]{Void.class}, (Class[])optionalArray[0].get("classArray"));
141141
assertArrayEquals(new Class[]{Void.class}, optionalArray[0].getClassArray("classArray"));
142142
}

org.springframework.transaction/src/main/java/org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
4444
new BeanFactoryTransactionAttributeSourceAdvisor();
4545
advisor.setTransactionAttributeSource(transactionAttributeSource());
4646
advisor.setAdvice(transactionInterceptor());
47-
advisor.setOrder(this.enableTx.getInt("order"));
47+
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
4848
return advisor;
4949
}
5050

0 commit comments

Comments
 (0)