From c2997f4dd976ee1ecabb9c149ef97faa8612f47f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 1 Dec 2011 13:12:59 +0000 Subject: [PATCH] backported Java 6 visibility bridge method pair (SPR-8660) --- .../AutowiredAnnotationBeanPostProcessor.java | 26 +++++++++---------- .../core/BridgeMethodResolver.java | 21 ++++++++++++++- 2 files changed, 32 insertions(+), 15 deletions(-) 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 8d483c0dadc..d20d09caf82 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 @@ -62,8 +62,11 @@ import org.springframework.util.ReflectionUtils; /** * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation * that autowires annotated fields, setter methods and arbitrary config methods. - * Such members to be injected are detected through a Java 5 annotation: - * by default, Spring's @{@link Autowired} and @{@link Value} annotations. + * Such members to be injected are detected through a Java 5 annotation: by default, + * Spring's {@link Autowired @Autowired} and {@link Value @Value} annotations. + * + *

Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation, + * if available, as a direct alternative to Spring's own @Autowired. * *

Only one constructor (at max) of any given bean class may carry this * annotation with the 'required' parameter set to true, @@ -78,14 +81,10 @@ import org.springframework.util.ReflectionUtils; *

Fields are injected right after construction of a bean, before any * config methods are invoked. Such a config field does not have to be public. * - *

Config methods may have an arbitrary name and any number of arguments; - * each of those arguments will be autowired with a matching bean in the - * Spring container. Bean property setter methods are effectively just - * a special case of such a general config method. Such config methods - * do not have to be public. - * - *

Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation, if - * available. + *

Config methods may have an arbitrary name and any number of arguments; each of + * those arguments will be autowired with a matching bean in the Spring container. + * Bean property setter methods are effectively just a special case of such a + * general config method. Config methods do not have to be public. * *

Note: A default AutowiredAnnotationBeanPostProcessor will be registered * by the "context:annotation-config" and "context:component-scan" XML tags. @@ -343,7 +342,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean } } for (Method method : targetClass.getDeclaredMethods()) { - Annotation annotation = findAutowiredAnnotation(method); + Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + Annotation annotation = BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod) ? + findAutowiredAnnotation(bridgedMethod) : findAutowiredAnnotation(method); if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isWarnEnabled()) { @@ -371,9 +372,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.core/src/main/java/org/springframework/core/BridgeMethodResolver.java b/org.springframework.core/src/main/java/org/springframework/core/BridgeMethodResolver.java index fac0d787519..1a67089bf71 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * 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. @@ -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 isVisibilityBridgeMethodPair(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()); + } + + }