I have a list of strings, that i would like to define in beans.xml.
<util:list id="myFractions" value-type="java.lang.String">
<value>#{ T(com.myapp.longname.verylong.WelcomeController).RED_FRACTION }</value>
<value>#{ T(com.myapp.longname.verylong.WelcomeController).BLUE_FRACTION }</value>
<value>#{ T(${my.prefix}).GREEN_FRACTION }</value>
</util:list>
It works fine, but each time I need to write the full qualified constant's name com.myapp.longname.verylong.WelcomeController
. I would like to write it only once. One solution I have found is to replace it with a property like my.prefix
so I can write only my short prefix instead of the real full path. But then I will need to pollute the global "namespace" with property that is only needed once. I would like to define a placeholder only for this list or at least only for this beans.xml file. I have already tried to define a property directly in beans.xml with PropertyPlaceholderConfigurer
and it works, but then all my inital properties are not available anymore.
So how can I avoid to writing com.myapp.longname.verylong.WelcomeController
each time in a list as a prefix and only define it once? Ideally something like
<util:list id="myFractions" value-type="java.lang.String">
<define-local-placeholder name="my.prefix" value="com.myapp.longname.verylong.WelcomeController" />
<value>#{ T(${my.prefix}).RED_FRACTION }</value>
<value>#{ T(${my.prefix}).BLUE_FRACTION }</value>
<value>#{ T(${my.prefix}).GREEN_FRACTION }</value>
</util:list>
CodePudding user response:
Try defining your prefix in properties file and use it in your beans.xml as shown here:
Best ways to deal with properties values in XML file in Spring, Maven and Eclipses
and here
Using Variable Substitution from Configuration Files in Spring
CodePudding user response:
A solution is to implement a FactoryBean
,
by extending the AbstractFactoryBean
class:
package test;
import java.util.*;
import org.springframework.beans.factory.config.AbstractFactoryBean;
public class ConstantListFactoryBean extends AbstractFactoryBean<List<Object>>
{
private Class<?> targetClass;
private List<String> constantNames;
public void setTargetClass(Class<?> targetClass)
{
this.targetClass = targetClass;
}
public void setConstantNames(List<String> constantNames)
{
this.constantNames = constantNames;
}
@Override
public Class<List> getObjectType()
{
return List.class;
}
@Override
protected List<Object> createInstance() throws Exception
{
ArrayList<Object> list = new ArrayList<Object>();
for(String name : constantNames)
list.add(targetClass.getField(name).get(null));
return list;
}
}
Here is a sample beans.xml that uses the ConstantListFactoryBean
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="colors" >
<property name="targetClass" value="test.Colors"/>
<property name="constantNames">
<list>
<value>RED</value>
<value>BLUE</value>
<value>GREEN</value>
</list>
</property>
</bean>
</beans>
And the sample class that holds the constants:
package test;
public class Colors
{
public static final String RED = "red";
public static final String BLUE = "blue";
public static final String GREEN = "green";
}
And finally, some code that shows that it works:
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
List colors = (List)context.getBean("colors");
System.out.println(colors);
}
}
Output:
[red, blue, green]