When trying to inject an Optional<T>
, Spring never calls my bean, and instead injects an Optional.empty()
.
Here is some sample code:
@Configuration
public class Initialize {
@Value("optionalValue")
private String testString;
@Bean (name = "getOptionalString")
public Optional<String> getOptionalString() {
return Optional.of(this.testString); //breakpoint put here, is never called
}
}
@Component
public class Test {
public Test(@Qualifier("getOptionalString") Optional<String> optional) {
// optional's value is Optional.empty() here
}
I noticed that (by putting a breakpoint) the @Bean
is never called. If I were to remove the Optional<String>
, and simply return a String
, then it works!
I know Spring
has its own optional dependency but I am perplexed as to why this doesn't work (whatever I read online says it should), and I also don't understand how it initialized it to Optional.empty()
?
Before Spring 4.3, we had to add an @Autowired annotation to the constructor. With newer versions, this is optional if the class has only one constructor.
The reasons why field injection is frowned upon are as follows: You cannot create immutable objects, as you can with constructor injection. Your classes have tight coupling with your DI container and cannot be used outside of it. Your classes cannot be instantiated (for example in unit tests) without reflection.
There are three types of injection: Constructor, Setter and Interface. Spring doesn't support the latest directly(as I have observed people saying).
Setter Injection is the preferred choice when a number of dependencies to be injected is a lot more than normal, if some of those arguments are optional than using a Builder design pattern is also a good option. In Summary, both Setter Injection and Constructor Injection have their own advantages and disadvantages.
Annotation of constructors for dependency injection has been optional since Spring Framework version 4.2. Constructor based dependency injection is certainly considered a best practice. There was a time I personally favored setter based injection, but have come around to constructor based.
The design principle of Inversion of Control emphasizes keeping the Java classes independent of each other and the container frees them from object creation and maintenance. These classes, managed by Spring, must adhere to the standard definition of Java-Bean. Dependency Injection in Spring also ensures loose-coupling between the classes.
Now, the secret sauce using Project Lombok for best practices in dependency injection is to: Now, Project Lombok will generate a constructor for all properties declared final. And Spring will automatically use the Lombok provided constructor to autowire the clase. This is a real nice way of doing this. Your code stays very clean.
Constructor based dependency injection is certainly considered a best practice. There was a time I personally favored setter based injection, but have come around to constructor based.
The documentation says:
you can express the non-required nature of a particular dependency through Java 8’s java.util.Optional, as the following example shows:
public class SimpleMovieLister { @Autowired public void setMovieFinder(Optional<MovieFinder> movieFinder) { ... } }
So using Optional as the type of a bean is not a good idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With