Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring bean with dynamic constructor value

Tags:

java

spring

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?

like image 898
Shamik Avatar asked Jan 07 '12 19:01

Shamik


3 Answers

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.

like image 83
skaffman Avatar answered Sep 19 '22 09:09

skaffman


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.

like image 23
Dan Hardiker Avatar answered Sep 17 '22 09:09

Dan Hardiker


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);
        ...
    }
}
like image 27
gpeche Avatar answered Sep 19 '22 09:09

gpeche