Browse Source

Consistently ignore bridge method on generated subclass for visibility purposes

Closes gh-33030
pull/33350/head
Juergen Hoeller 2 years ago
parent
commit
2c3c3831c1
  1. 36
      spring-context/src/test/java/org/springframework/context/annotation/configuration/AutowiredConfigurationTests.java
  2. 5
      spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java

36
spring-context/src/test/java/org/springframework/context/annotation/configuration/AutowiredConfigurationTests.java

@ -26,6 +26,7 @@ import jakarta.inject.Provider; @@ -26,6 +26,7 @@ import jakarta.inject.Provider;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -43,6 +44,7 @@ import org.springframework.context.support.GenericApplicationContext; @@ -43,6 +44,7 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import static org.assertj.core.api.Assertions.assertThat;
@ -183,6 +185,14 @@ class AutowiredConfigurationTests { @@ -183,6 +185,14 @@ class AutowiredConfigurationTests {
context.close();
}
@Test
void testValueInjectionWithAccidentalAutowiredAnnotations() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ValueConfigWithAccidentalAutowiredAnnotations.class);
doTestValueInjection(context);
context.close();
}
private void doTestValueInjection(BeanFactory context) {
System.clearProperty("myProp");
@ -494,6 +504,32 @@ class AutowiredConfigurationTests { @@ -494,6 +504,32 @@ class AutowiredConfigurationTests {
}
@Configuration
static class ValueConfigWithAccidentalAutowiredAnnotations implements InitializingBean {
boolean invoked;
@Override
public void afterPropertiesSet() {
Assert.state(!invoked, "Factory method must not get invoked on startup");
}
@Bean @Scope("prototype")
@Autowired
public TestBean testBean(@Value("#{systemProperties[myProp]}") Provider<String> name) {
invoked = true;
return new TestBean(name.get());
}
@Bean @Scope("prototype")
@Autowired
public TestBean testBean2(@Value("#{systemProperties[myProp]}") Provider<String> name2) {
invoked = true;
return new TestBean(name2.get());
}
}
@Configuration
static class PropertiesConfig {

5
spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java

@ -276,8 +276,13 @@ public final class BridgeMethodResolver { @@ -276,8 +276,13 @@ public final class BridgeMethodResolver {
*/
public static boolean isVisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) {
if (bridgeMethod == bridgedMethod) {
// Same method: for common purposes, return true to proceed as if it was a visibility bridge.
return true;
}
if (ClassUtils.getUserClass(bridgeMethod.getDeclaringClass()) != bridgeMethod.getDeclaringClass()) {
// Method on generated subclass: return false to consistently ignore it for visibility purposes.
return false;
}
return (bridgeMethod.getReturnType().equals(bridgedMethod.getReturnType()) &&
bridgeMethod.getParameterCount() == bridgedMethod.getParameterCount() &&
Arrays.equals(bridgeMethod.getParameterTypes(), bridgedMethod.getParameterTypes()));

Loading…
Cancel
Save