Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change in how Spring 5 handles null Beans?

So, I have the following application:

@SpringBootApplication
public class AutonullApplication {

  public static void main(String[] args) {
    SpringApplication.run(AutonullApplication.class, args);
  }

  @Bean
  First first() {
    return null;
  }

  public class First {
  }

  @Service
  public class Second {

    private final First first;

    public Second(First first) {
      this.first = first;
    }

    @PostConstruct
    public void print() {
      System.out.println("First = " + first);
    }
  }

}

which tries to inject a bean of type First into a service of type Second. But the bean has a value of null. This code works fine in Spring Boot 1.5.10 (and so Spring 4), but fails in Spring Boot 2.0 (and Spring 5):

Description:

Parameter 1 of constructor in eu.plumbr.autonull.AutonullApplication$Second required a bean of type 'eu.plumbr.autonull.AutonullApplication$First' that could not be found.

Is anybody aware of any mention of such change in the official documentation?

like image 251
Nikem Avatar asked Mar 01 '18 07:03

Nikem


People also ask

How does a Spring container destroy beans?

And finally, the bean is destroyed when the spring container is closed. Therefore, if we want to execute some code on the bean instantiation and just after closing the spring container, then we can write that code inside the custom init() method and the destroy() method.

Are there any ways to pass value of property of a bean as null?

In Spring, you can uses this special <null /> tag to pass a “null” value into constructor argument or property.

Which steps of beans lifecycle can be overridden or controlled?

Spring bean life cycle can be controlled in the following ways. Instantiation by using: InitializingBean callback interface. Custom init() method from the bean configuration file.

How does Spring know which bean to use?

The identifier of the parameter matches the name of one of the beans from the context (which is the same as the name of the method annotated with @Bean that returns its value). In this case, Spring chooses that bean for which the name is the same as the parameter.


1 Answers

Yes, this is a breaking change in Spring Framework 5. Arguably, such setup is weird and we wanted to tighten those rules a little bit.

If you request to inject First and you provide null, then it's more consistent to consider that bean isn't provided. You can then query the context for the presence of First. @spencergibb already explained how you can use Optional, or you can use ObjectProvider<First> as an injection point:

@Service
public class Second {

    private final First first;

    public Second(ObjectProvider<First> first) {
        this.first = first.getIfAvailable(); // return null
    }

}
like image 177
Stephane Nicoll Avatar answered Sep 21 '22 18:09

Stephane Nicoll