Thomas Beauvais
Thomas Beauvais

Reputation: 1656

RestController method injection doesn't support singleton (Annotation Driven)

The documentation says that the default bean scope for Spring is a singleton.

I couldn't find anything about method level injections bypassing this scope.

With this configuration

@Configuration
public class ApplicationConfiguration {
    @Bean
    public ModuleProvider getModuleProvider() {
        return new ModuleProvider();
    }
}

Method One (which I expect for both outcomes):

@RestController
@Scope(value = "request")
@RequestMapping(value = "/application")
public class ApplicationController {
    @Autowired
    ModuleProvider moduleProvider;

    @RequestMapping
    public String showModules() {
        return moduleProvider.toString();
    }
}

Hitting it twice, the output is..

application.ModuleProvider@673f63cb
application.ModuleProvider@673f63cb

Method Two:

@RestController
@Scope(value = "request")
@RequestMapping(value = "/application")
public class ApplicationController {
    @Autowired   
    @RequestMapping
    public String showModules(ModuleProvider moduleProvider) {
        return moduleProvider.toString();
    }
}

Hitting it twice, the output is..

application.ModuleProvider@1cc4fbcb
application.ModuleProvider@57248dbf

Upvotes: 1

Views: 887

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280102

(You should actually see it three times in your second case.)

@Autowired is only processed when a bean is created and must have fields or methods injected.

When preparing your ApplicationController bean, Spring will find the showModules method annotated with @Autowired and invoke it by injecting the ModuleProvider bean from the @Configuration class.

After that, Spring is done with injections for ApplicationController.

When you subsequently send requests, Spring MVC takes over. This ignores @Autowired entirely. By default, arguments for @RequestMapping annotated methods in controller types are handled by HandlerMethodArgumentResolver. In this case, an instance of type ModelAttributeMethodProcessor (or its ServletModelAttributeMethodProcessor subclass) will generate the argument for the parameter of type ModuleProvider.

Each time it will create a new one. These instances are completely separate from the ApplicationContext. It's the same process as using a form parameter in your handler method.

Extra reading:

Upvotes: 4

Related Questions