diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index fdc50b0335..5878369297 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -16,6 +16,9 @@ package org.springframework.beans.factory.annotation; +import static org.springframework.core.BridgeMethodResolver.findBridgedMethod; +import static org.springframework.core.BridgeMethodResolver.isJava6VisibilityBridgeMethodPair; + import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; @@ -35,7 +38,6 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValues; @@ -50,7 +52,6 @@ import org.springframework.beans.factory.config.InstantiationAwareBeanPostProces import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.core.BridgeMethodResolver; import org.springframework.core.GenericTypeResolver; import org.springframework.core.MethodParameter; import org.springframework.core.Ordered; @@ -342,7 +343,10 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean } } for (Method method : targetClass.getDeclaredMethods()) { - Annotation annotation = findAutowiredAnnotation(method); + Method bridgedMethod = findBridgedMethod(method); + Annotation annotation = isJava6VisibilityBridgeMethodPair(method, bridgedMethod) ? + findAutowiredAnnotation(bridgedMethod) : + findAutowiredAnnotation(method); if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isWarnEnabled()) { @@ -370,9 +374,6 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean private Annotation findAutowiredAnnotation(AccessibleObject ao) { for (Class type : this.autowiredAnnotationTypes) { - if (ao instanceof Method) { - ao = BridgeMethodResolver.findBridgedMethod((Method) ao); - } Annotation annotation = ao.getAnnotation(type); if (annotation != null) { return annotation; diff --git a/org.springframework.context/src/test/java/org/springframework/beans/factory/annotation/BridgeMethodAutowiringTests.java b/org.springframework.context/src/test/java/org/springframework/beans/factory/annotation/BridgeMethodAutowiringTests.java new file mode 100644 index 0000000000..822da917c5 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/beans/factory/annotation/BridgeMethodAutowiringTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.beans.factory.annotation; + +import static org.junit.Assert.assertNotNull; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.stereotype.Component; + +public class BridgeMethodAutowiringTests { + + @Test + public void SPR_8434() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(UserServiceImpl.class, Foo.class); + ctx.refresh(); + assertNotNull(ctx.getBean(UserServiceImpl.class).object); + } + +} + + +abstract class GenericServiceImpl { + + public abstract void setObject(D object); + +} + + +class UserServiceImpl extends GenericServiceImpl { + + protected Foo object; + + @Inject + @Named("userObject") + public void setObject(Foo object) { + this.object = object; + } +} + +@Component("userObject") +class Foo { } + diff --git a/org.springframework.core/src/main/java/org/springframework/core/BridgeMethodResolver.java b/org.springframework.core/src/main/java/org/springframework/core/BridgeMethodResolver.java index fac0d78751..c0ff0e93b1 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/BridgeMethodResolver.java +++ b/org.springframework.core/src/main/java/org/springframework/core/BridgeMethodResolver.java @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; @@ -210,4 +211,22 @@ public abstract class BridgeMethodResolver { return ReflectionUtils.findMethod(type, bridgeMethod.getName(), bridgeMethod.getParameterTypes()); } + /** + * Compare the signatures of the bridge method and the method which it bridges. If + * the parameter and return types are the same, it is a 'visibility' bridge method + * introduced in Java 6 to fix http://bugs.sun.com/view_bug.do?bug_id=6342411. + * See also http://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html + * @return whether signatures match as described + */ + public static boolean isJava6VisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) { + Assert.isTrue(bridgeMethod != null); + Assert.isTrue(bridgedMethod != null); + if (bridgeMethod == bridgedMethod) { + return true; + } + return Arrays.equals(bridgeMethod.getParameterTypes(), bridgedMethod.getParameterTypes()) + && bridgeMethod.getReturnType().equals(bridgedMethod.getReturnType()); + } + + }