Skip to content

Commit 8be36fa

Browse files
committed
introduced dedicated Jsr330ScopeMetadataResolver
1 parent 4fb68be commit 8be36fa

File tree

2 files changed

+113
-15
lines changed

2 files changed

+113
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright 2002-2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.context.annotation;
18+
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
import java.util.Set;
22+
23+
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
24+
import org.springframework.beans.factory.config.BeanDefinition;
25+
26+
/**
27+
* Simple {@link ScopeMetadataResolver} implementation that follows JSR-330 scoping rules:
28+
* defaulting to prototype scope unless {@link javax.inject.Singleton} is present.
29+
*
30+
* <p>This scope resolver can be used with {@link ClassPathBeanDefinitionScanner} and
31+
* {@link AnnotatedBeanDefinitionReader} for standard JSR-330 compliance. However,
32+
* in practice, you will typically use Spring's rich default scoping instead - or extend
33+
* this resolver with custom scoping annotations that point to extended Spring scopes.
34+
*
35+
* @author Juergen Hoeller
36+
* @since 3.0
37+
* @see #registerScope
38+
* @see #resolveScopeName
39+
* @see ClassPathBeanDefinitionScanner#setScopeMetadataResolver
40+
* @see AnnotatedBeanDefinitionReader#setScopeMetadataResolver
41+
*/
42+
public class Jsr330ScopeMetadataResolver implements ScopeMetadataResolver {
43+
44+
private final Map<String, String> scopeMap = new HashMap<String, String>();
45+
46+
47+
public Jsr330ScopeMetadataResolver() {
48+
registerScope("javax.inject.Singleton", BeanDefinition.SCOPE_SINGLETON);
49+
}
50+
51+
52+
/**
53+
* Register an extended JSR-330 scope annotation, mapping it onto a
54+
* specific Spring scope by name.
55+
* @param annotationType the JSR-330 annotation type as a Class
56+
* @param scopeName the Spring scope name
57+
*/
58+
public final void registerScope(Class annotationType, String scopeName) {
59+
this.scopeMap.put(annotationType.getName(), scopeName);
60+
}
61+
62+
/**
63+
* Register an extended JSR-330 scope annotation, mapping it onto a
64+
* specific Spring scope by name.
65+
* @param annotationType the JSR-330 annotation type by name
66+
* @param scopeName the Spring scope name
67+
*/
68+
public final void registerScope(String annotationType, String scopeName) {
69+
this.scopeMap.put(annotationType, scopeName);
70+
}
71+
72+
/**
73+
* Resolve the given annotation type into a named Spring scope.
74+
* <p>The default implementation simply checks against registered scopes.
75+
* Can be overridden for custom mapping rules, e.g. naming conventions.
76+
* @param annotationType the JSR-330 annotation type
77+
* @return the Spring scope name
78+
*/
79+
protected String resolveScopeName(String annotationType) {
80+
return this.scopeMap.get(annotationType);
81+
}
82+
83+
84+
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
85+
ScopeMetadata metadata = new ScopeMetadata();
86+
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
87+
if (definition instanceof AnnotatedBeanDefinition) {
88+
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
89+
Set<String> annTypes = annDef.getMetadata().getAnnotationTypes();
90+
String found = null;
91+
for (String annType : annTypes) {
92+
Set<String> metaAnns = annDef.getMetadata().getMetaAnnotationTypes(annType);
93+
if (metaAnns.contains("javax.inject.Scope")) {
94+
if (found != null) {
95+
throw new IllegalStateException("Found ambiguous scope annotations on bean class [" +
96+
definition.getBeanClassName() + "]: " + found + ", " + annType);
97+
}
98+
found = annType;
99+
String scopeName = resolveScopeName(annType);
100+
if (scopeName == null) {
101+
throw new IllegalStateException(
102+
"Unsupported scope annotation - not mapped onto Spring scope name: " + annType);
103+
}
104+
metadata.setScopeName(scopeName);
105+
}
106+
}
107+
}
108+
return metadata;
109+
}
110+
111+
}

org.springframework.context/src/test/java/org/springframework/context/annotation/jsr330/SpringAtInjectTck.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,9 @@
2929
import org.atinject.tck.auto.accessories.Cupholder;
3030
import org.atinject.tck.auto.accessories.SpareTire;
3131

32-
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
33-
import org.springframework.beans.factory.config.BeanDefinition;
3432
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
33+
import org.springframework.context.annotation.Jsr330ScopeMetadataResolver;
3534
import org.springframework.context.annotation.Primary;
36-
import org.springframework.context.annotation.ScopeMetadata;
37-
import org.springframework.context.annotation.ScopeMetadataResolver;
3835
import org.springframework.context.support.GenericApplicationContext;
3936

4037
/**
@@ -46,17 +43,7 @@ public class SpringAtInjectTck {
4643
public static Test suite() {
4744
GenericApplicationContext ac = new GenericApplicationContext();
4845
AnnotatedBeanDefinitionReader bdr = new AnnotatedBeanDefinitionReader(ac);
49-
bdr.setScopeMetadataResolver(new ScopeMetadataResolver() {
50-
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
51-
ScopeMetadata metadata = new ScopeMetadata();
52-
if (definition instanceof AnnotatedBeanDefinition) {
53-
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
54-
metadata.setScopeName(annDef.getMetadata().hasAnnotation(javax.inject.Singleton.class.getName()) ?
55-
BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
56-
}
57-
return metadata;
58-
}
59-
});
46+
bdr.setScopeMetadataResolver(new Jsr330ScopeMetadataResolver());
6047

6148
bdr.registerBean(Convertible.class);
6249
bdr.registerBean(DriversSeat.class, Drivers.class);

0 commit comments

Comments
 (0)