13

I am trying to write a ValidatorFactory which will give me a validator based on its type

public Validator getNewValidator(ValidatorType type){

    switch:
         case a : new Validator1();
         break;
          case b : new Validator2();
        break;

}

I want to write using spring xml beans definition

I can use method injection but it will let me create only one object and the method does

not take any arguments.

I don't want to use FactoryBean.. I am just looking whether we can do this using spring xml

bean definition.

4
  • why don't you want to use FactoryBean? Commented Jun 29, 2010 at 13:55
  • there is no reason as such ..i just want to know can is there any way to create conditional beans..just out of curiosity Commented Jun 29, 2010 at 14:11
  • This is exactly what FactoryBean is for. Don't fight it :) Commented Jun 29, 2010 at 14:13
  • I am just looking for an answer is it feasible to do using spring xml bean definition Commented Jun 30, 2010 at 2:45

5 Answers 5

22

you can do conditional bean injection with plain xml. The "ref" attribute can be triggered by property values from a property file and thus create conditional beans depending on property values. This feature is not documented but it works perfect.

<bean id="validatorFactory" class="ValidatorFactory">
<property name="validator" ref="${validatorType}" />
</bean>

<bean id="validatorTypeOne" class="Validator1" lazy-init="true" />
<bean id="validatorTypeTwo" class="Validator2" lazy-init="true" />

And the content of the property file would be:

validatorType=validatorTypeOne

To use the property file in your xml just add this context to the top of your spring config

<context:property-placeholder location="classpath:app.properties" />
Sign up to request clarification or add additional context in comments.

4 Comments

Just need a little more explanation on how could I do validatorType=validatorTypeOne in XML code?
validatorType=validatorTypeOne is the content in a property file and the syntax ${validatorType} gets expanded to the value of the property which is in this case: validatorTypeOne. As this points to a bean reference id an instance of the class Validator1 gets created and assigned to the property in ValidatorFactory. Got it?
No, I am a bit confuse on the statement validatorType=validatorTypeOne. What if I need it to be validatorTypeTwo? And also I got syntax error on ref="${validatorType}". I need some reference on this ref thing so that I can understand it clearly.
Just be wary of trying this with any beans that use SmartLifecycle. See this thread for details.
3

For complex cases (more complex than the one exposed), Spring JavaConfig could be your friend.

1 Comment

Before downvoting my answer, please check its date. Spring JavaConfig wasn't very widespread yet in 2010.
2

If you are using annotation (@Autowired, @Qualifier etc) instead of xml, you are not able to make conditional beans work (at least at current version 3). This is due to @Qualifier does not support expression

@Qualifier(value="${validatorType}")

More information is at https://stackoverflow.com/a/7813228/418439

Comments

1

I had an slightly different requirements. In my case I wanted to have encoded password in production but plain text in development. Also, I didn't have access to parent bean parentEncoder. This is how I managed to achieve that:

<bean id="plainTextPassword" class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"/>
<bean id="shaPassword" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
    <constructor-arg type="int" value="256"/>
</bean> 

<bean id="parentEncoder" class="org.springframework.aop.framework.ProxyFactoryBean"> 
  <property name="targetSource"> 
    <bean class="org.springframework.aop.target.HotSwappableTargetSource"> 
      <constructor-arg ref="${password.encoding}Password"/> 
    </bean> 
  </property> 
</bean>

Of course, I defined password.encoding in a property file with possible values as sha or plainText.

Comments

0

You should be able to do this:

<bean id="myValidator" factory-bean="validatorFactory" factory-method="getNewValidator" scope="prototype">
    <constructor-arg><ref bean="validatorType"/></constructor-arg>
</bean>

<bean id="validatorType" ... />

Of course, it uses an automatically configured FactoryBean underneath but you avoid any Spring dependency in your code.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.