Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I want to use a annotated prototype bean in my controller. But spring is creating a singleton bean instead. Here is the code for that:

@Component
@Scope("prototype")
public class LoginAction {
  private int counter;
  public LoginAction(){
    System.out.println(" counter is:" + counter);
  public String getStr() {
    return " counter is:"+(++counter);

Controller code:

@Controller
public class HomeController {
    @Autowired
    private LoginAction loginAction;
    @RequestMapping(value="/view", method=RequestMethod.GET)
    public ModelAndView display(HttpServletRequest req){
        ModelAndView mav = new ModelAndView("home");
        mav.addObject("loginAction", loginAction);
        return mav;
    public void setLoginAction(LoginAction loginAction) {
        this.loginAction = loginAction;
    public LoginAction getLoginAction() {
        return loginAction;

Velocity template:

 LoginAction counter: ${loginAction.str}

Spring config.xml has component scanning enabled:

    <context:annotation-config />
    <context:component-scan base-package="com.springheat" />
    <mvc:annotation-driven />

I'm getting an incremented count each time. Can't figure out where am I going wrong!

Update

As suggested by @gkamal, I made HomeController webApplicationContext-aware and it solved the problem.

updated code:

@Controller
public class HomeController {
    @Autowired
    private WebApplicationContext context;
    @RequestMapping(value="/view", method=RequestMethod.GET)
    public ModelAndView display(HttpServletRequest req){
        ModelAndView mav = new ModelAndView("home");
        mav.addObject("loginAction", getLoginAction());
        return mav;
    public LoginAction getLoginAction() {
        return (LoginAction) context.getBean("loginAction");
                I wish I could double upvote you for implementing the correct answer in your code for others to see the actual difference
– Ali Nem
                Dec 25, 2016 at 5:23

Scope prototype means that every time you ask spring (getBean or dependency injection) for an instance it will create a new instance and give a reference to that.

In your example a new instance of LoginAction is created and injected into your HomeController . If you have another controller into which you inject LoginAction you will get a different instance.

If you want a different instance for each call - then you need to call getBean each time - injecting into a singleton bean will not achieve that.

I made the controller ApplicationContextAware and did getBean and I'm getting the fresh bean every time. Thanks guys!!! – tintin Oct 1, 2011 at 18:26 How does this work if the bean would have had request scope instead of prototype scope. Would you still need to retrieve the bean with context.getBean(..)? – dr jerry Feb 24, 2015 at 10:07 Or use a scoped proxy, i.e. @Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) – svenmeier Jul 11, 2016 at 15:12

Since Spring 2.5 there's a very easy (and elegant) way to achieve that.

You can just change the params proxyMode and value of the @Scope annotation.

With this trick you can avoid to write extra code or to inject the ApplicationContext every time that you need a prototype inside a singleton bean.

Example:

@Service 
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)  
public class LoginAction {}

With the config above LoginAction (inside HomeController) is always a prototype even though the controller is a singleton.

As mentioned by nicholas.hauschild injecting Spring context is not a good idea. In your case, @Scope("request") is enough to fix it. But let say you need several instances of LoginAction in controller method. In this case, I would recommend to create the bean of Supplier (Spring 4 solution):

    @Bean
    public Supplier<LoginAction> loginActionSupplier(LoginAction loginAction){
        return () -> loginAction;

Then inject it into controller:

@Controller
public class HomeController {
    @Autowired
    private  Supplier<LoginAction> loginActionSupplier;  
                I would suggest injecting springs ObjectFactory which serves the same purpose as supplier, but can be defined as a normal @Bean by which I mean no need to return a lambda.
– xenoterracide
                Nov 29, 2018 at 19:14
                There's already Spring-specific annotations, though; doesn't seem like that's much of a concern.
– Dave Newton
                Oct 1, 2011 at 21:05
                @Dave, Good point.  There are alternatives for some of the DI stuff (JSR 311), but it may be harder to rid yourself of everything Spring dependent in this example.  I suppose I am really just advocating the factory-method here...
– nicholas.hauschild
                Oct 1, 2011 at 21:17
                +1 for injecting a singleton LoginActionFactory into the Controller, but factory-method doesn't seem like it would solve the issue as it just creates another spring bean via the factory. Injecting that bean into the singleton Controller won't address the problem.
– Brad Cupit
                Feb 21, 2013 at 15:11

A protoype bean injected inside a singelton bean will behave like singelton untill expilictly called for creating a new instance by get bean.

context.getBean("Your Bean")
  

By default, Spring beans are singletons. The problem arises when we try to wire beans of different scopes. For example, a prototype bean into a singleton. This is known as the scoped bean injection problem.

Another way to solve the problem is method injection with the @Lookup annotation.

Here is a nice article on this issue of injecting prototype beans into a singleton instance with multiple solutions.

https://www.baeldung.com/spring-inject-prototype-bean-into-singleton

class with @Configuration

@Bean
@RequestScope //composed annotation for @Scope(value=...proxyMode=...)
public LoginAction requestScopedBean() {
    return new LoginAction ();
@Controller
public class HomeController {
    @Resource(name = "requestScopedBean")
    private LoginAction loginAction;
    //...your code here
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.