Chciałem mieć możliwość wyrażenia, że dane property ma mieć wartość 2 * wartość innego property.
Po krótkim googlowaniu nie udało mi się nic znaleźć i stwierdziłem, że łatwo samemu coś takiego napisać. W tym celu stworzyłem własną klasę FactoryBean, której zadaniem było wykonywanie operacji mnożenia na injectowanych parametrach.
private TypeConverter typeConverter = new SimpleTypeConverter();
public void setParam1(Object param1) {
this.param1 = param1;
}
public void setParam2(Object param2) {
this.param2 = param2;
}
public Object getObject() throws Exception {
Object result = null;
BigDecimal param1Converted = convert(param1);
BigDecimal param2Converted = convert(param2);
BigDecimal result = param1Converted.multiply(param2Converted);
return result;
}
private BigDecimal convert(Object obj) {
return (BigDecimal) typeConverter.convertIfNecessary(obj, BigDecimal.class);
}
public Class getObjectType() {
return BigDecimal.class;
}
Wyglądało to całkiem,całkiem ale pomyślałem, że bardzo prosto byłoby zbudować bardziej generyczne rozwiązanie. Implementacja FactoryBean dla innej 2-argumentowej operacji byłaby prawie identyczny, a jedynie różniłaby się oepracją na klasie BigDecimal. Dodatkowo chciałem mieć możliwość specyfikowania typu danych wyniku operacji arytmetycznej.
Generyczny ArithmeticOperationFactoryBean:
public abstract class ArithmeticOperationFactoryBean implements FactoryBean,
InitializingBean {
private TypeConverter typeConverter = new SimpleTypeConverter();
private Object param1;
private Object param2;
private Class<?> resultType;
public void setResultType(Class<?> resultType) {
this.resultType = resultType;
}
public void setParam1(Object param1) {
this.param1 = param1;
}
public void setParam2(Object param2) {
this.param2 = param2;
}
@Override
public void afterPropertiesSet() throws Exception {
if (param1 == null || param2 == null) {
throw new IllegalArgumentException(
"operation arguments can not be null");
}
if(resultType == null){
resultType = BigDecimal.class;
}
}
@Override
public Object getObject() throws Exception {
Object result = null;
BigDecimal param1Converted = convert(param1);
BigDecimal param2Converted = convert(param2);
BigDecimal operationResult = executeOperation(param1Converted,
param2Converted);
result = operationResult;
if (resultType != null) {
result = convert(operationResult, resultType);
}
return result;
}
protected abstract BigDecimal executeOperation(BigDecimal param1Converted,
BigDecimal param2Converted);
@SuppressWarnings("unchecked")
private <T> T convert(Object obj, Classtype) {
return (T) typeConverter.convertIfNecessary(obj, type);
}
private BigDecimal convert(Object param) {
return convert(param, BigDecimal.class);
}
@Override
public Class<?> getObjectType() {
return resultType;
}
@Override
public boolean isSingleton() {
return true;
}
}
FactoryBean odpowiedzialny za operacje:
public class MultiplicationFactoryBean extends ArithmeticOperationFactoryBean {
@Override
protected BigDecimal executeOperation(BigDecimal param1,
BigDecimal param2) {
return param1.multiply(param2);
}
}
Użycie takiego FactoryBean w konfiguracji wygląda w następujący sposób:
Konfiguracja definiuje w context dwa beany:"foo" typu java.lang.Double oraz "myInteger" typu java.lang.Integer. Wartość foo jest 24.
Zamiast dziedziczenia może lepiej byłoby zastosować tu wzorzec strategy, ale jest to w takim przypadku chyba pomijalne...
Dodatkowo, ekspsresywność rozwiązania nie rzuca na kolana, ale dla prostych zastosowań nadaję się moim zdaniem co najmniej przyzwoicie.
Brak komentarzy:
Prześlij komentarz