Browse Source

Consistent detection of meta-annotation attributes via ASM

Issue: SPR-13394
pull/866/head
Juergen Hoeller 10 years ago
parent
commit
3430f7623c
  1. 32
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
  2. 4
      spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java
  3. 5
      spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java
  4. 16
      spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java
  5. 25
      spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java

32
spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

@ -27,6 +27,7 @@ import org.junit.Test;
import org.springframework.aop.scope.ScopedObject; import org.springframework.aop.scope.ScopedObject;
import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
@ -426,6 +427,28 @@ public class ConfigurationClassPostProcessorTests {
RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean"); RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean");
assertEquals("Repository<String>", bean.stringRepository.toString()); assertEquals("Repository<String>", bean.stringRepository.toString());
assertEquals("Repository<Integer>", bean.integerRepository.toString()); assertEquals("Repository<Integer>", bean.integerRepository.toString());
assertTrue(AopUtils.isCglibProxy(bean.stringRepository));
assertTrue(AopUtils.isCglibProxy(bean.integerRepository));
}
@Test
public void genericsBasedInjectionWithScopedProxyUsingAsm() {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(beanFactory);
beanFactory.addBeanPostProcessor(bpp);
RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class.getName());
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("annotatedBean", bd);
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(ScopedProxyRepositoryConfiguration.class.getName()));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory);
beanFactory.freezeConfiguration();
RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean");
assertEquals("Repository<String>", bean.stringRepository.toString());
assertEquals("Repository<Integer>", bean.integerRepository.toString());
assertTrue(AopUtils.isCglibProxy(bean.stringRepository));
assertTrue(AopUtils.isCglibProxy(bean.integerRepository));
} }
@Test @Test
@ -783,6 +806,13 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Retention(RetentionPolicy.RUNTIME)
@Scope(scopeName = "prototype")
public @interface PrototypeScoped {
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
@Configuration @Configuration
public static class ScopedProxyRepositoryConfiguration { public static class ScopedProxyRepositoryConfiguration {
@ -798,7 +828,7 @@ public class ConfigurationClassPostProcessorTests {
} }
@Bean @Bean
@Scope(scopeName = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) @PrototypeScoped
public Repository<Integer> integerRepo() { public Repository<Integer> integerRepo() {
return new Repository<Integer>() { return new Repository<Integer>() {
@Override @Override

4
spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java

@ -111,7 +111,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
@Override @Override
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) { public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getMergedAnnotationAttributes(getIntrospectedClass(), return AnnotatedElementUtils.getMergedAnnotationAttributes(getIntrospectedClass(),
annotationName, classValuesAsString, this.nestedAnnotationsAsMap); annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
} }
@Override @Override
@ -122,7 +122,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
@Override @Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getAllAnnotationAttributes(getIntrospectedClass(), return AnnotatedElementUtils.getAllAnnotationAttributes(getIntrospectedClass(),
annotationName, classValuesAsString, this.nestedAnnotationsAsMap); annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
} }
@Override @Override

5
spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java

@ -66,6 +66,7 @@ public class StandardMethodMetadata implements MethodMetadata {
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap; this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
} }
/** /**
* Return the underlying Method. * Return the underlying Method.
*/ */
@ -121,7 +122,7 @@ public class StandardMethodMetadata implements MethodMetadata {
@Override @Override
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) { public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod, return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod,
annotationName, classValuesAsString, this.nestedAnnotationsAsMap); annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
} }
@Override @Override
@ -132,7 +133,7 @@ public class StandardMethodMetadata implements MethodMetadata {
@Override @Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod, return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod,
annotationName, classValuesAsString, this.nestedAnnotationsAsMap); annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
} }
} }

16
spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java

@ -59,7 +59,8 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
* to ensure that the hierarchical ordering of the entries is preserved. * to ensure that the hierarchical ordering of the entries is preserved.
* @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes * @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes
*/ */
protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<String, AnnotationAttributes>(4); protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap =
new LinkedMultiValueMap<String, AnnotationAttributes>(4);
protected final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>(4); protected final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>(4);
@ -84,7 +85,8 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
String className = Type.getType(desc).getClassName(); String className = Type.getType(desc).getClassName();
this.annotationSet.add(className); this.annotationSet.add(className);
return new AnnotationAttributesReadingVisitor(className, this.attributesMap, this.metaAnnotationMap, this.classLoader); return new AnnotationAttributesReadingVisitor(
className, this.attributesMap, this.metaAnnotationMap, this.classLoader);
} }
@ -116,7 +118,8 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
@Override @Override
public boolean isAnnotated(String annotationName) { public boolean isAnnotated(String annotationName) {
return (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && this.attributesMap.containsKey(annotationName)); return (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) &&
this.attributesMap.containsKey(annotationName));
} }
@Override @Override
@ -127,8 +130,7 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
@Override @Override
public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) { public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes( AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes(
this.attributesMap, this.attributesMap, this.metaAnnotationMap, annotationName);
this.metaAnnotationMap, annotationName);
return AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString); return AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString);
} }
@ -145,8 +147,8 @@ this.attributesMap,
return null; return null;
} }
for (AnnotationAttributes raw : attributes) { for (AnnotationAttributes raw : attributes) {
for (Map.Entry<String, Object> entry : for (Map.Entry<String, Object> entry : AnnotationReadingVisitorUtils.convertClassValues(
AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString).entrySet()) { this.classLoader, raw, classValuesAsString).entrySet()) {
allAttributes.add(entry.getKey(), entry.getValue()); allAttributes.add(entry.getKey(), entry.getValue());
} }
} }

25
spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java

@ -16,7 +16,7 @@
package org.springframework.core.type.classreading; package org.springframework.core.type.classreading;
import java.util.List; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -56,7 +56,9 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
protected final Set<MethodMetadata> methodMetadataSet; protected final Set<MethodMetadata> methodMetadataSet;
protected final MultiValueMap<String, AnnotationAttributes> attributeMap = protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>(4);
protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap =
new LinkedMultiValueMap<String, AnnotationAttributes>(4); new LinkedMultiValueMap<String, AnnotationAttributes>(4);
@ -77,7 +79,8 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
String className = Type.getType(desc).getClassName(); String className = Type.getType(desc).getClassName();
this.methodMetadataSet.add(this); this.methodMetadataSet.add(this);
return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader); return new AnnotationAttributesReadingVisitor(
className, this.attributesMap, this.metaAnnotationMap, this.classLoader);
} }
@Override @Override
@ -107,19 +110,19 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
@Override @Override
public boolean isAnnotated(String annotationName) { public boolean isAnnotated(String annotationName) {
return this.attributeMap.containsKey(annotationName); return this.attributesMap.containsKey(annotationName);
} }
@Override @Override
public Map<String, Object> getAnnotationAttributes(String annotationName) { public AnnotationAttributes getAnnotationAttributes(String annotationName) {
return getAnnotationAttributes(annotationName, false); return getAnnotationAttributes(annotationName, false);
} }
@Override @Override
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) { public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
List<AnnotationAttributes> attributes = this.attributeMap.get(annotationName); AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes(
return (attributes == null ? null : AnnotationReadingVisitorUtils.convertClassValues( this.attributesMap, this.metaAnnotationMap, annotationName);
this.classLoader, attributes.get(0), classValuesAsString)); return (AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString));
} }
@Override @Override
@ -129,11 +132,11 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
@Override @Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
if (!this.attributeMap.containsKey(annotationName)) { if (!this.attributesMap.containsKey(annotationName)) {
return null; return null;
} }
MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<String, Object>(); MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<String, Object>();
for (AnnotationAttributes annotationAttributes : this.attributeMap.get(annotationName)) { for (AnnotationAttributes annotationAttributes : this.attributesMap.get(annotationName)) {
for (Map.Entry<String, Object> entry : AnnotationReadingVisitorUtils.convertClassValues( for (Map.Entry<String, Object> entry : AnnotationReadingVisitorUtils.convertClassValues(
this.classLoader, annotationAttributes, classValuesAsString).entrySet()) { this.classLoader, annotationAttributes, classValuesAsString).entrySet()) {
allAttributes.add(entry.getKey(), entry.getValue()); allAttributes.add(entry.getKey(), entry.getValue());

Loading…
Cancel
Save