From f4219ca06bbd1c324567ab9e74d0d18693359810 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 18 Sep 2014 23:45:42 +0200 Subject: [PATCH] Consistent exclusion of bridge methods in annotation post-processors (for Java 8 compatibility) Issue: SPR-12187 --- .../AutowiredAnnotationBeanPostProcessor.java | 6 +-- ...wiredAnnotationBeanPostProcessorTests.java | 54 +++++++++++++++++++ .../CommonAnnotationBeanPostProcessor.java | 5 +- ...ersistenceAnnotationBeanPostProcessor.java | 2 +- 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index 2207c78e01b..cec20e5963e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -392,9 +392,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean } for (Method method : targetClass.getDeclaredMethods()) { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); - AnnotationAttributes annotation = BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod) ? + AnnotationAttributes ann = BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod) ? findAutowiredAnnotation(bridgedMethod) : findAutowiredAnnotation(method); - if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { + if (ann != null && !method.isBridge() && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isWarnEnabled()) { logger.warn("Autowired annotation is not supported on static methods: " + method); @@ -406,7 +406,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean logger.warn("Autowired annotation should be used on methods with actual parameters: " + method); } } - boolean required = determineRequiredStatus(annotation); + boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); currElements.add(new AutowiredMethodElement(method, required, pd)); } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java index 7ffea747c6c..4ca7eae9cca 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java @@ -26,6 +26,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; import org.junit.Ignore; import org.junit.Test; @@ -1756,6 +1757,18 @@ public class AutowiredAnnotationBeanPostProcessorTests { assertSame(bf.getBean(StockMovementDaoImpl.class), service.stockMovementDao); } + @Test + public void testBridgeMethodHandling() { + DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); + AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); + bpp.setBeanFactory(bf); + bf.addBeanPostProcessor(bpp); + bf.registerBeanDefinition("bean1", new RootBeanDefinition(MyCallable.class)); + bf.registerBeanDefinition("bean2", new RootBeanDefinition(SecondCallable.class)); + bf.registerBeanDefinition("bean3", new RootBeanDefinition(FooBar.class)); + assertNotNull(bf.getBean(FooBar.class)); + } + public static class ResourceInjectionBean { @@ -2755,4 +2768,45 @@ public class AutowiredAnnotationBeanPostProcessorTests { private StockMovementDao stockMovementDao; } + + public static class MyCallable implements Callable { + + @Override + public Thread call() throws Exception { + return null; + } + } + + + public static class SecondCallable implements Callable{ + + @Override + public Thread call() throws Exception { + return null; + } + } + + + public static abstract class Foo> { + + private RT obj; + + protected void setObj(RT obj) { + if (this.obj != null) { + throw new IllegalStateException("Already called"); + } + this.obj = obj; + } + } + + + public static class FooBar extends Foo { + + @Override + @Autowired + public void setObj(MyCallable obj) { + super.setObj(obj); + } + } + } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java index 3e38a3f4b8e..2f6d981467c 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java @@ -58,7 +58,6 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.core.BridgeMethodResolver; import org.springframework.core.MethodParameter; import org.springframework.core.Ordered; import org.springframework.jndi.support.SimpleJndiBeanFactory; @@ -348,9 +347,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean } } for (Method method : targetClass.getDeclaredMethods()) { - method = BridgeMethodResolver.findBridgedMethod(method); - Method mostSpecificMethod = BridgeMethodResolver.findBridgedMethod(ClassUtils.getMostSpecificMethod(method, clazz)); - if (method.equals(mostSpecificMethod)) { + if (!method.isBridge() && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (webServiceRefClass != null && method.isAnnotationPresent(webServiceRefClass)) { if (Modifier.isStatic(method.getModifiers())) { throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods"); diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java index 9def582587d..7647a6cabe8 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java @@ -402,7 +402,7 @@ public class PersistenceAnnotationBeanPostProcessor for (Method method : targetClass.getDeclaredMethods()) { PersistenceContext pc = method.getAnnotation(PersistenceContext.class); PersistenceUnit pu = method.getAnnotation(PersistenceUnit.class); - if ((pc != null || pu != null) && + if ((pc != null || pu != null) && !method.isBridge() && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { throw new IllegalStateException("Persistence annotations are not supported on static methods");