Sven
Sven

Reputation: 952

@Autowired in Spring MVC @Controller does not work on a private field

I have a Spring MVC Controller in a very XML-slimmed application, we use a lot of annotations and as little config as possible. The Controller is working and it also has a number of resource values injected. But I've experienced a really strange behavior with this controller; annotated private fields referencing other components will not be injected. This will not work.

@Controller
public class EntranceUnitController {

    @Value("${remote.baseUrl}")
    private String baseUrl = "http://localhost";

    @Value("${remote.port}")
    private String pushPort = "8080";

    @Autowired
    private HttpClientFactory httpClientFactory;

    ...

It seems that the httpClientFactory isn't there yet when the private fields are set, if I set a break point to inspect the value there is of course null set when the controller is created.

BUT, if I make a setter for the component and annotate the set-method instead of the private field the controller works as expected.

@Controller
public class EntranceUnitController {

    @Value("${remote.baseUrl}")
    private String baseUrl = "http://localhost";

    @Value("${remote.port}")
    private String pushPort = "8080";

    private HttpClientFactory httpClientFactory;

    @Autowired
    public void setHttpClientFactory(HttpClientFactory httpClientFactory) {
        this.httpClientFactory = httpClientFactory;
    }

    ...

To me this is really annoying. Isn't the auto wiring injection for annotated values happening at the same time regardless injection point? I.e. why does it matter that the object is injected with a setter? I thought that private field injections are directly followed by constructs and setters, me start to think I'm wrong in that case...

Upvotes: 2

Views: 3275

Answers (1)

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340933

Seems like your dependencies are in fact injected, you are just putting a breakpoint in the wrong moment (too early) and the dependencies aren't injected yet, despite class being already created.

Remember that, unless you are using constructor injection, the first place where you can use injected dependencies is @PostConstruct method:

@Controller
public class EntranceUnitController {

    @Autowired
    private HttpClientFactory httpClientFactory;

    @PostConstruct
    public void init() {
        httpClientFactory  //should not be null
    }

Upvotes: 4

Related Questions