Skip to content

Commit 5ed9046

Browse files
committed
BeanMethodInterceptor does not pass on null arguments for singleton beans
Issue: SPR-13887
1 parent d6700b7 commit 5ed9046

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -364,8 +364,20 @@ public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object
364364
if (alreadyInCreation) {
365365
beanFactory.setCurrentlyInCreation(beanName, false);
366366
}
367-
Object beanInstance = (!ObjectUtils.isEmpty(beanMethodArgs) ?
368-
beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName));
367+
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
368+
if (useArgs && beanFactory.isSingleton(beanName)) {
369+
// Stubbed null arguments just for reference purposes,
370+
// expecting them to be autowired for regular singleton references?
371+
// A safe assumption since @Bean singleton arguments cannot be optional...
372+
for (Object arg : beanMethodArgs) {
373+
if (arg == null) {
374+
useArgs = false;
375+
break;
376+
}
377+
}
378+
}
379+
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
380+
beanFactory.getBean(beanName));
369381
if (beanInstance != null && !ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
370382
String msg = String.format("@Bean method %s.%s called as a bean reference " +
371383
"for type [%s] but overridden by non-compatible bean instance of type [%s].",

spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -592,17 +592,23 @@ public void testCircularDependencyWithApplicationContext() {
592592
}
593593

594594
@Test
595-
public void testPrototypeArgumentsThroughBeanMethodCall() {
595+
public void testPrototypeArgumentThroughBeanMethodCall() {
596596
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithPrototype.class);
597597
ctx.getBean(FooFactory.class).createFoo(new BarArgument());
598598
}
599599

600600
@Test
601-
public void testSingletonArgumentsThroughBeanMethodCall() {
601+
public void testSingletonArgumentThroughBeanMethodCall() {
602602
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithSingleton.class);
603603
ctx.getBean(FooFactory.class).createFoo(new BarArgument());
604604
}
605605

606+
@Test
607+
public void testNullArgumentThroughBeanMethodCall() {
608+
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithNull.class);
609+
ctx.getBean("aFoo");
610+
}
611+
606612

607613
// -------------------------------------------------------------------------
608614

@@ -1137,15 +1143,15 @@ static class BeanArgumentConfigWithPrototype {
11371143

11381144
@Bean
11391145
@Scope("prototype")
1140-
public DependingFoo foo(final BarArgument bar) {
1146+
public DependingFoo foo(BarArgument bar) {
11411147
return new DependingFoo(bar);
11421148
}
11431149

11441150
@Bean
11451151
public FooFactory fooFactory() {
11461152
return new FooFactory() {
11471153
@Override
1148-
public DependingFoo createFoo(final BarArgument bar) {
1154+
public DependingFoo createFoo(BarArgument bar) {
11491155
return foo(bar);
11501156
}
11511157
};
@@ -1156,27 +1162,47 @@ public DependingFoo createFoo(final BarArgument bar) {
11561162
static class BeanArgumentConfigWithSingleton {
11571163

11581164
@Bean @Lazy
1159-
public DependingFoo foo(final BarArgument bar) {
1165+
public DependingFoo foo(BarArgument bar) {
11601166
return new DependingFoo(bar);
11611167
}
11621168

11631169
@Bean
11641170
public FooFactory fooFactory() {
11651171
return new FooFactory() {
11661172
@Override
1167-
public DependingFoo createFoo(final BarArgument bar) {
1173+
public DependingFoo createFoo(BarArgument bar) {
11681174
return foo(bar);
11691175
}
11701176
};
11711177
}
11721178
}
11731179

1180+
@Configuration
1181+
static class BeanArgumentConfigWithNull {
1182+
1183+
@Bean
1184+
public DependingFoo aFoo() {
1185+
return foo(null);
1186+
}
1187+
1188+
@Bean @Lazy
1189+
public DependingFoo foo(BarArgument bar) {
1190+
return new DependingFoo(bar);
1191+
}
1192+
1193+
@Bean
1194+
public BarArgument bar() {
1195+
return new BarArgument();
1196+
}
1197+
}
1198+
11741199
static class BarArgument {
11751200
}
11761201

11771202
static class DependingFoo {
11781203

11791204
DependingFoo(BarArgument bar) {
1205+
Assert.notNull(bar);
11801206
}
11811207
}
11821208

0 commit comments

Comments
 (0)