This solution is courtesy Chris Harris UK.
Step 1: Create a bean factory post processor as shown in Listing 1
Listing 1 : StaticInitializerBeanFactoryPostProcessor .java
/**
*
*/
package org.opengarage.spring.postprocessor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
* @author dhrubo
*
*/
public class StaticInitializerBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private Map classes;
private BeanWrapperImpl bri;
public StaticInitializerBeanFactoryPostProcessor() {
bri = new BeanWrapperImpl();
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
for (Iterator classIterator = classes.keySet().iterator(); classIterator.hasNext(); ) {
String className = (String)classIterator.next();
//System.out.println("Class " + className + ":");
Map vars = (Map)classes.get(className);
Class c = null;
try {
c = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new NoSuchBeanDefinitionException("Class not found for " + className);
}
Method[] methods = c.getMethods();
for (Iterator fieldIterator = vars.keySet().iterator(); fieldIterator.hasNext(); ) {
String fieldName = (String)fieldIterator.next();
Object value = vars.get(fieldName);
Method method = findStaticSetter(methods, fieldName);
if (method == null) {
throw new RuntimeException("No static setter method found for class " +
className + ", field " + fieldName,null);
}
//System.out.println("\tFound method " + method.getName() + " for field " + fieldName + ", value " + value);
Object newValue = bri.doTypeConversionIfNecessary(value, getPropertyType(method));
try {
method.invoke(null, new Object[] {newValue});
} catch (Exception e) {
throw new RuntimeException("Invocation of method " + method.getName() +
" on class " + className + " with value " + value + " failed.", e);
}
}
}
}
private Class getPropertyType(Method setter) {
Class params[] = setter.getParameterTypes();
if (params.length != 1) {
throw new RuntimeException("bad write method arg count: " + setter);
}
return params[0];
}
/**
* Look for a static setter method for field named fieldName in Method[].
* Return null if none found.
* @param methods
* @param fieldName
* @return
*/
private Method findStaticSetter(Method[] methods, String fieldName) {
String methodName = setterName(fieldName);
for (int i=0; i<methods.length; i++) {
if (methods[i].getName().equals(methodName) &&
Modifier.isStatic(methods[i].getModifiers())) {
return methods[i];
}
}
return null;
}
/**
* return the standard setter name for field fieldName
* @param fieldName
* @return
*/
private String setterName(String fieldName) {
String nameToUse = null;
if (fieldName.length() == 1) {
if (Character.isLowerCase(fieldName.charAt(0))) {
nameToUse = fieldName.toUpperCase();
} else {
nameToUse = fieldName;
}
} else {
if (Character.isLowerCase(fieldName.charAt(0)) && Character.isLowerCase(fieldName.charAt(1))) {
nameToUse = fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
} else {
nameToUse = fieldName;
}
}
return "set" + nameToUse;
}
public void setClasses(Map classes) {
this.classes = classes;
}
}
Step 2 : Create your simple test class
Listing 2 : Test.java
/**
*
*/
package org.opengarage.spring.test;
import java.util.Properties;
/**
* @author dhrubo
*
*/
public class Test {
private static Properties properties;
/**
* @return the properties
*/
public static Properties getProperties() {
return properties;
}
/**
* @param properties the properties to set
*/
public static void setProperties(Properties properties) {
Test.properties = properties;
}
}
Step 3 : Finally wire up everything in Spring configuration file
Listing 3 - Spring-config.xml
<bean class="org.opengarage.spring.postprocessor.StaticInitializerBeanFactoryPostProcessor">
<property name="classes">
<map>
<entry key="org.opengarage.pingscape.test.Test">
<map>
<entry key="properties">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<value>classpath:org/opengarage/spring/test/jdbc.properties</value>
</property>
</bean>
</entry>
</map>
</entry>
</map>
</property>
</bean>
0 comments:
Post a Comment