Fixed @Bean meta-annotation detection when using ASM
This turned out to be a bug in the ASM-based AnnotationMetadata implementation where has/getAnnotatedMethods didn't consider meta-annotations., in contrast to its StandardAnnotationMetadata sibling. Issue: SPR-10488
This commit is contained in:
parent
61a3d04e91
commit
105e176a80
|
@ -23,6 +23,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
@ -84,6 +85,19 @@ public class BeanMethodQualificationTests {
|
||||||
assertThat(pojo.testBean.getName(), equalTo("interesting"));
|
assertThat(pojo.testBean.getName(), equalTo("interesting"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCustomWithAsm() {
|
||||||
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
|
ctx.registerBeanDefinition("customConfig", new RootBeanDefinition(CustomConfig.class.getName()));
|
||||||
|
RootBeanDefinition customPojo = new RootBeanDefinition(CustomPojo.class.getName());
|
||||||
|
customPojo.setLazyInit(true);
|
||||||
|
ctx.registerBeanDefinition("customPojo", customPojo);
|
||||||
|
ctx.refresh();
|
||||||
|
assertFalse(ctx.getBeanFactory().containsSingleton("testBean1"));
|
||||||
|
CustomPojo pojo = ctx.getBean(CustomPojo.class);
|
||||||
|
assertThat(pojo.testBean.getName(), equalTo("interesting"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCustomWithAttributeOverride() {
|
public void testCustomWithAttributeOverride() {
|
||||||
AnnotationConfigApplicationContext ctx =
|
AnnotationConfigApplicationContext ctx =
|
||||||
|
|
|
@ -29,7 +29,6 @@ import org.springframework.asm.Type;
|
||||||
import org.springframework.core.annotation.AnnotationAttributes;
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.core.type.MethodMetadata;
|
import org.springframework.core.type.MethodMetadata;
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
|
@ -48,13 +47,13 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
|
||||||
|
|
||||||
protected final ClassLoader classLoader;
|
protected final ClassLoader classLoader;
|
||||||
|
|
||||||
protected final Set<String> annotationSet = new LinkedHashSet<String>();
|
protected final Set<String> annotationSet = new LinkedHashSet<String>(4);
|
||||||
|
|
||||||
protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>(4);
|
protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>(4);
|
||||||
|
|
||||||
protected final MultiValueMap<String, AnnotationAttributes> attributeMap = new LinkedMultiValueMap<String, AnnotationAttributes>(4);
|
protected final MultiValueMap<String, AnnotationAttributes> attributeMap = new LinkedMultiValueMap<String, AnnotationAttributes>(4);
|
||||||
|
|
||||||
protected final MultiValueMap<String, MethodMetadata> methodMetadataMap = new LinkedMultiValueMap<String, MethodMetadata>();
|
protected final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>(4);
|
||||||
|
|
||||||
|
|
||||||
public AnnotationMetadataReadingVisitor(ClassLoader classLoader) {
|
public AnnotationMetadataReadingVisitor(ClassLoader classLoader) {
|
||||||
|
@ -64,7 +63,7 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||||
return new MethodMetadataReadingVisitor(name, access, this.getClassName(), this.classLoader, this.methodMetadataMap);
|
return new MethodMetadataReadingVisitor(name, access, getClassName(), this.classLoader, this.methodMetadataSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -141,17 +140,22 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasAnnotatedMethods(String annotationType) {
|
public boolean hasAnnotatedMethods(String annotationType) {
|
||||||
return this.methodMetadataMap.containsKey(annotationType);
|
for (MethodMetadata methodMetadata : this.methodMetadataSet) {
|
||||||
|
if (methodMetadata.isAnnotated(annotationType)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<MethodMetadata> getAnnotatedMethods(String annotationType) {
|
public Set<MethodMetadata> getAnnotatedMethods(String annotationType) {
|
||||||
List<MethodMetadata> list = this.methodMetadataMap.get(annotationType);
|
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(4);
|
||||||
if (CollectionUtils.isEmpty(list)) {
|
for (MethodMetadata methodMetadata : this.methodMetadataSet) {
|
||||||
return new LinkedHashSet<MethodMetadata>(0);
|
if (methodMetadata.isAnnotated(annotationType)) {
|
||||||
|
annotatedMethods.add(methodMetadata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(list.size());
|
|
||||||
annotatedMethods.addAll(list);
|
|
||||||
return annotatedMethods;
|
return annotatedMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.core.type.classreading;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.asm.AnnotationVisitor;
|
import org.springframework.asm.AnnotationVisitor;
|
||||||
import org.springframework.asm.MethodVisitor;
|
import org.springframework.asm.MethodVisitor;
|
||||||
|
@ -51,27 +52,28 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
|
||||||
|
|
||||||
protected final ClassLoader classLoader;
|
protected final ClassLoader classLoader;
|
||||||
|
|
||||||
protected final MultiValueMap<String, MethodMetadata> methodMetadataMap;
|
protected final Set<MethodMetadata> methodMetadataSet;
|
||||||
|
|
||||||
protected final MultiValueMap<String, AnnotationAttributes> attributeMap = new LinkedMultiValueMap<String, AnnotationAttributes>(2);
|
protected final MultiValueMap<String, AnnotationAttributes> attributeMap =
|
||||||
|
new LinkedMultiValueMap<String, AnnotationAttributes>(4);
|
||||||
|
|
||||||
|
|
||||||
public MethodMetadataReadingVisitor(String name, int access, String declaringClassName, ClassLoader classLoader,
|
public MethodMetadataReadingVisitor(String name, int access, String declaringClassName,
|
||||||
MultiValueMap<String, MethodMetadata> methodMetadataMap) {
|
ClassLoader classLoader, Set<MethodMetadata> methodMetadataSet) {
|
||||||
|
|
||||||
super(SpringAsmInfo.ASM_VERSION);
|
super(SpringAsmInfo.ASM_VERSION);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.access = access;
|
this.access = access;
|
||||||
this.declaringClassName = declaringClassName;
|
this.declaringClassName = declaringClassName;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
this.methodMetadataMap = methodMetadataMap;
|
this.methodMetadataSet = methodMetadataSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
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.methodMetadataMap.add(className, this);
|
this.methodMetadataSet.add(this);
|
||||||
return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader);
|
return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +108,7 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> getAnnotationAttributes(String annotationType,
|
public Map<String, Object> getAnnotationAttributes(String annotationType, boolean classValuesAsString) {
|
||||||
boolean classValuesAsString) {
|
|
||||||
List<AnnotationAttributes> attributes = this.attributeMap.get(annotationType);
|
List<AnnotationAttributes> attributes = this.attributeMap.get(annotationType);
|
||||||
return (attributes == null ? null : AnnotationReadingVisitorUtils.convertClassValues(
|
return (attributes == null ? null : AnnotationReadingVisitorUtils.convertClassValues(
|
||||||
this.classLoader, attributes.get(0), classValuesAsString));
|
this.classLoader, attributes.get(0), classValuesAsString));
|
||||||
|
@ -119,9 +120,8 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MultiValueMap<String, Object> getAllAnnotationAttributes(
|
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) {
|
||||||
String annotationType, boolean classValuesAsString) {
|
if (!this.attributeMap.containsKey(annotationType)) {
|
||||||
if(!this.attributeMap.containsKey(annotationType)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<String, Object>();
|
MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<String, Object>();
|
||||||
|
|
Loading…
Reference in New Issue