Spring Dependency Injection

23 Jun 2019 java spring

There are three ways to inject dependencies into beans in Spring, listed below. In this post we’ll quickly go over the three ways of injection.

  1. Constructor

Constructor-based injection

Constructor-based injection is typically the best way to go about injecting dependencies into beans. With constructor-based injection we’re able to enforce two main ideas,

  1. Missing consturctor-based beans will cause a BeanDefinitionException if the dependency is missing

Lets see constructor-based injection in action.

@Service
public class ExampleService {
    private final ExampleConstructorDependency exampleConstructorDependency;

    @Autowired // As of Spring 4.3 this is no longer needed
    public ExampleService(ExampleConstructorDependency exampleConstructorDependency) {
        this.exampleContructorDependency = exampleConstructorDependency;
    }
}

Setter-base injection

The second way to inject dependencies into beans is by using setter-based injection. Setter-based injection utilizes the typical setX to inject the dependency. Spring recommends utilizing setter-based injection when you’re injecting optional dependencies.

@Service
public class ExampleService {
    private ExampleSetterDependency exampleSetterDependency;

    @Autowired
    public void setExampleSetterDependency(ExampleSetterDependency exampleSetterDependency) {
        this.exampleSetterDependency = exampleSetterDependency;
    }
}

Field-based injection

The thrid way to inject dependencies into beans is by using field-based injection. Field-based injection is the simpliest and cleanest looking but it comes with some heavy drawbacks that make it very frowned upon.

  1. Utilizing Java reflection to inject the dependencies which is costlier and riskier than constructor or setter injection
@Service
public class ExampleService {
    @Autowired
    private ExampleFieldDependency exampleFieldDependency;
}

Conclusion

In my daily work we have a team standard that all dependencies must be injected via constructor-based injection and all dependencies must be private final. This standard allows us to know that we’re always going to be threadsafe in our dependencies and we’re going to be consistent across all of the applications we manage. This directive doesn’t work for all teams, which is totally fine, but the one thing I would stress is if you or your team is using field-based injection, have them switch to atleast setter-based injection. It maybe a bit uglier but you won’t run into any of the multiple field-based injecttion drawbacks.