Shamik
Shamik

Reputation: 7108

spring bean with dynamic constructor value

I need to create an Object which is in-complete without the constructor argument. Something like this

Class A  {
  private final int timeOut
  public A(int timeout)
  {
     this.timeOut = timeout;
   }
 //...
}

I would like this Bean to be spring managed, so that I can use Spring AOP later.

<bean id="myBean" class="A" singleton="false">
</bean>

However my bean needs timeout to be passed as a dynamic value - is there a way to create a spring managed bean with dynamic value being injedcted in the constructor?

Upvotes: 18

Views: 21471

Answers (3)

skaffman
skaffman

Reputation: 403471

BeanFactory has a getBean(String name, Object... args) method which, according to the javadoc, allows you to specify constructor arguments which are used to override the bean definition's own arguments. So you could put a default value in the beans file, and then specify the "real" runtime values when required, e.g.

<bean id="myBean" class="A" scope="prototype">
   <constructor-arg value="0"/> <!-- dummy value -->
</bean>

and then:

getBean("myBean", myTimeoutValue);

I haven't tried this myself, but it should work.

P.S. scope="prototype" is now preferable to singleton="false", which is deprecated syntax - it's more explicit, but does the same thing.

Upvotes: 28

gpeche
gpeche

Reputation: 22514

Do it explicitly:

interface Bean {
    void setTimeout(int timeout);
}

class BeanImpl implements Bean {
    private int timeout;

    @Override
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
    ...
}

<bean id="bean" class="BeanImpl" scope="prototype">
    ...
    <!-- Nothing about timeout here -->
    ...
</bean>

class Client {
    private Bean bean;
    public void setBean(Bean bean) {
        this.bean = bean;
    }
    ...
    public void methodThatUsesBean() {
        int timeout = calculateTimeout();
        bean.setTimeout(timeout);
        ...
    }
}

Upvotes: 1

Dan Hardiker
Dan Hardiker

Reputation: 3053

Two options spring (no pun intended) to mind:


1. create a timeout factory, and use that as the constructor parameter. You can create a bean which implements FactoryBean, and it's job is to create other beans. So if you had something that generates salt's for encryption, you could have it return from getObject() a EncryptionSalt object. In your case you're wanting to generate Integers.

Here is an example: http://www.java2s.com/Code/Java/Spring/SpringFactoryBeanDemo.htm


2. create a timeout bean that wraps an int that's dynamically set, and leave that in the "prototype" state so it's created each time Instead of going to the hassle of creating a factory, the EncryptionSalt object could just be declared as a prototype bean, so when it's injected a new object is created each time. Place the logic into the constructor or somewhere else.


It somewhat depends what value you want the timeout to actually be.

Upvotes: 1

Related Questions