-
Notifications
You must be signed in to change notification settings - Fork 38.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
For @Bean
method that returns null
, @Autowired
injects NullBean
instead of null
for cached arguments
#30485
Comments
Have you tried latest version? IIRC this is fixed long long ago. |
I can verify injection works fine but get bean doesn't work, tested with v6.0.8. import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ContextConfiguration(classes = NullBeanTests.Config.class)
@ExtendWith(SpringExtension.class)
public class NullBeanTests {
@Autowired
private String myBean;
@Test
void testInjection() { // will pass
assertThat(myBean).isNull();
}
@Test
public void testGetBean() { // will fail
try (var ctx = new AnnotationConfigApplicationContext()) {
ctx.register(Config.class);
ctx.refresh();
assertThat(ctx.getBean("myBean")).isNull();
}
}
static class Config {
@Bean
public String myBean() {
return null;
}
}
} |
Not yet tried 6.x, but all 5.x have this issue. |
Injection works, but applicationContext.getBean() doesn't work. I updated the issue title. |
@qiangyt, thanks for reporting this. @quaff, thanks for providing the autowiring/injection test case. Interestingly, it turns out that autowiring does not consistently work either. Here's a modified version of the combined tests which demonstrates that. import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig(NullBeanTests.Config.class)
@TestMethodOrder(OrderAnnotation.class)
class NullBeanTests {
@Autowired
String myBean;
@Test
@Order(1)
void fieldInjection() {
assertThat(myBean).isNull();
}
@Test
@Order(2)
void parameterInjection(@Autowired String myBean) {
assertThat(myBean).isNull();
}
@Test
@Order(99)
void getBean() {
try (var ctx = new AnnotationConfigApplicationContext(Config.class)) {
Object bean = ctx.getBean("myBean");
System.err.println(bean != null ? bean.getClass().getName() : null);
assertThat(bean).isNull();
}
}
// @Configuration
static class Config {
@Bean
String myBean() {
return null;
}
}
}
If you run If you run the If you change the If you change the If you only change the So, there is something interesting going on here, and it's definitely a bug (and possibly a regression). We'll look into it. |
@Bean
method that returns null
, ApplicationContext.getBean()
and @Autowired
result in NullBean
instead of null
In terms of intended behavior, So for |
I knew we used Is that documented anywhere? |
@Bean
method that returns null
, ApplicationContext.getBean()
and @Autowired
result in NullBean
instead of null
@Bean
method that returns null
, @Autowired
sometimes injects a NullBean
instead of null
NullBean is an internal class (the class is not public/protected), it is a bit strange to be the result of ApplicationContext.getBean() API. |
sorry for making mistake of close/re-open the issue. |
Another case is, for a factory method that returns null, ApplicationContext.getBean("myBean", MyBean.class) will raise a BeanNotOfRequiredTypeException with a message "Bean named 'myBean' is expected to be of type 'org.springframework.beans.factory.support.MyBean' but was actually of type 'org.springframework.beans.factory.support.NullBean", I feel it strange for users. |
Good point, Sam, I'm afraid it might not be fully documented. In this view, a "bean" is never Stubbing out a bean instance with As for |
This turns out to be a bug in shortcut resolution for cached field/method arguments. We're replacing the full dependency resolution algorithm with a In addition, I'll also add a few documentation notes towards not expecting |
@Bean
method that returns null
, @Autowired
sometimes injects a NullBean
instead of null
@Bean
method that returns null
, @Autowired
injects NullBean
instead of null
for cached arguments
Affects: 5.x
See below test case:
The text was updated successfully, but these errors were encountered: