提交 310bdbcb 编写于 作者: J Juergen Hoeller

@Bean processing explicitly ignores bridge methods (for method overrides with...

@Bean processing explicitly ignores bridge methods (for method overrides with return type narrowing on JDK 8)

Issue: SPR-11718
(cherry picked from commit 656fc52f)
上级 1f630a5f
...@@ -23,6 +23,7 @@ import org.junit.Test; ...@@ -23,6 +23,7 @@ import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator; import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.interceptor.SimpleTraceInterceptor; import org.springframework.aop.interceptor.SimpleTraceInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
...@@ -55,6 +56,39 @@ public class BeanMethodPolymorphismTests { ...@@ -55,6 +56,39 @@ public class BeanMethodPolymorphismTests {
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean")); assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
} }
@Test
public void beanMethodOverridingOnASM() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.registerBeanDefinition("config", new RootBeanDefinition(OverridingConfig.class.getName()));
ctx.setAllowBeanDefinitionOverriding(false);
ctx.refresh();
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
assertEquals("overridden", ctx.getBean("testBean", TestBean.class).toString());
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
}
@Test
public void beanMethodOverridingWithNarrowedReturnType() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(NarrowedOverridingConfig.class);
ctx.setAllowBeanDefinitionOverriding(false);
ctx.refresh();
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
assertEquals("overridden", ctx.getBean("testBean", TestBean.class).toString());
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
}
@Test
public void beanMethodOverridingWithNarrowedReturnTypeOnASM() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.registerBeanDefinition("config", new RootBeanDefinition(NarrowedOverridingConfig.class.getName()));
ctx.setAllowBeanDefinitionOverriding(false);
ctx.refresh();
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
assertEquals("overridden", ctx.getBean("testBean", TestBean.class).toString());
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
}
@Test @Test
public void beanMethodOverloadingWithoutInheritance() { public void beanMethodOverloadingWithoutInheritance() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
...@@ -173,6 +207,26 @@ public class BeanMethodPolymorphismTests { ...@@ -173,6 +207,26 @@ public class BeanMethodPolymorphismTests {
} }
static class ExtendedTestBean extends TestBean {
}
@Configuration
static class NarrowedOverridingConfig extends BaseConfig {
@Bean @Lazy
@Override
public ExtendedTestBean testBean() {
return new ExtendedTestBean() {
@Override
public String toString() {
return "overridden";
}
};
}
}
@Configuration @Configuration
static class ConfigWithOverloading { static class ConfigWithOverloading {
......
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -128,7 +128,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements ...@@ -128,7 +128,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
public boolean hasAnnotatedMethods(String annotationType) { public boolean hasAnnotatedMethods(String annotationType) {
Method[] methods = getIntrospectedClass().getDeclaredMethods(); Method[] methods = getIntrospectedClass().getDeclaredMethods();
for (Method method : methods) { for (Method method : methods) {
if (AnnotatedElementUtils.isAnnotated(method, annotationType)) { if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationType)) {
return true; return true;
} }
} }
...@@ -140,7 +140,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements ...@@ -140,7 +140,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
Method[] methods = getIntrospectedClass().getDeclaredMethods(); Method[] methods = getIntrospectedClass().getDeclaredMethods();
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(); Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>();
for (Method method : methods) { for (Method method : methods) {
if (AnnotatedElementUtils.isAnnotated(method, annotationType)) { if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationType)) {
annotatedMethods.add(new StandardMethodMetadata(method, this.nestedAnnotationsAsMap)); annotatedMethods.add(new StandardMethodMetadata(method, this.nestedAnnotationsAsMap));
} }
} }
......
...@@ -25,6 +25,7 @@ import java.util.Set; ...@@ -25,6 +25,7 @@ import java.util.Set;
import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.AnnotationVisitor;
import org.springframework.asm.MethodVisitor; import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Opcodes;
import org.springframework.asm.Type; 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;
...@@ -57,8 +58,7 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito ...@@ -57,8 +58,7 @@ 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(LinkedMultiValueMap, String) * @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes(LinkedMultiValueMap, String)
*/ */
protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<String, AnnotationAttributes>( protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<String, AnnotationAttributes>(4);
4);
protected final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>(4); protected final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>(4);
...@@ -70,6 +70,11 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito ...@@ -70,6 +70,11 @@ 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) {
// Skip bridge methods - we're only interested in original annotation-defining user methods.
// On JDK 8, we'd otherwise run into double detection of the same annotated method...
if ((access & Opcodes.ACC_BRIDGE) != 0) {
return super.visitMethod(access, name, desc, signature, exceptions);
}
return new MethodMetadataReadingVisitor(name, access, getClassName(), this.classLoader, this.methodMetadataSet); return new MethodMetadataReadingVisitor(name, access, getClassName(), this.classLoader, this.methodMetadataSet);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册