0
votes

I have following spring bean with Prototype scope. In the AppRunner class, I want a new bean to injected by spring within the for loop (if loop count is 2, then i want only 2 new beans to be injected).

But spring injects a new bean every time the setter methods of the SimpleBean is called.

SimpleBean.java

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = 
ScopedProxyMode.TARGET_CLASS)
public class SimpleBean {
    private String id;
    private Long value;
    public String getId() {
       return id;
    }

    public void setId(String id) {
       this.id = id;
    }

    public Long getValue() {
        return value;
    }

    public void setValue(Long value) {
        this.value = value;
    }
}

AppRunner.java

@Component
public class AppRunner {

    @Autowired
    SimpleBean simpleBean;

    public void execute(List<Output> results){
        List<SimpleBean> finalResults = new ArrayList<SimpleBean>();
        for(Output o : results){
            simpleBean.setId(o.getAppId());
            simpleBean.setValue(o.getAppVal());
            finalResults.add(simpleBean);
        }
    }
}

Output.java

public class Output {
    private String appId;
    private Long appVal;

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public Long getAppVal() {
        return appVal;
    }

    public void setAppVal(Long appVal) {
        this.appVal = appVal;
    }
}
1

1 Answers

0
votes

Unfortunately prototype scope doesn't work like this. When your AppRunner bean is instantiated by the container it is asking for its dependencies. Then a new instance of SimpleBean is created. This instance stays as dependency. Prototype scope starts working when you will have multiple beans with dependency on SimpleBean. Like:

@Component
class BeanOne {
    @Autowired
    SimpleBean bean; //will have its own instance
}

@Component
class BeanTwo {
    @Autowired
    SimpleBean bean; //another instance
}

There is one rather straightforward update which can lead to your desired behaviour. You can remove autowired dependency and ask for a new dependency in your loop from context. It would look like this.

@Component
public class AppRunner {

    @Autowired
    ApplicationContext context;

    public void execute(List<Output> results){
        List<SimpleBean> finalResults = new ArrayList<SimpleBean>();
        for(Output o : results) {
            SimpleBean simpleBean = context.getBean(SimpleBean.class);
            simpleBean.setId(o.getAppId());
            simpleBean.setValue(o.getAppVal());
            finalResults.add(simpleBean);
        }
    }
}

Other option could be technique called Method injection. It is described in the relevant documentation for prototype scope. You can take a look here 7.5.3 Singleton beans with prototype-bean dependencies