@AllArgsConstructor and Constructor Injection with Spring: is private final needed?

Viewed 10084

Let's say I have the following constructor injection (not Autowiring):

@Service
public class FooService {

    private final OrderService orderService;

    public FooService(OrderService orderService) {
        this.orderService = orderService;
    }
}

That can be replaced with:

@Service
@AllArgsConstructor
public class FooService {

    private final OrderService orderService;

}

Do I need to declare this as private and final to inject this service? Does Lombok take care of this like they do with @Data and beans? Any side-effects?

2 Answers

You should use @RequiredArgsConstructor instead, you need a single primary constructor to fill the required fields. So you marked them final and use this annotation to generate a primary constructor. @AllArgsConstructor is bug-prone, because it may produce multiple constructors which Spring may fail to handle. In your particular case the results of @AllArgsConstructor and @RequiredArgsConstructor just happen to be the same, because you have just one final field.

Note that, Spring documentation encourages the usage of constructor-based injection (https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-setter-injection), and recommends to avoid using several injection techniques together.

@Service
@RequiredArgsConstructor
public class FooService {

    private final OrderService orderService;

}

According to documentation

@AllArgsConstructor generates a constructor with 1 parameter for each field in your class. Fields marked with @NonNull result in null checks on those parameters.

So, no, it does not make your fields private & final as for example @Value annotation.

Related