我有一个名为Document.java的POJO,带有100+成员变量。有一个转换层,在该层中,我获取所需的数据,将其转换并存储在文档类中。
在转换层中,我只想在满足某个标准(基于可用上下文)的情况下设置一个成员变量。
所以看起来是这样的:
if(shouldGetExecuted1(context.getXXX())){
document.setField1(tranformDataForField1(availableData1));
}
if(shouldGetExecuted2(context.getXXX())){
document.setField2(tranformDataForField2(availableData2));
}
我想对所有的100+字段都这样做。有干净的方法吗?
附加信息
我不想在这里使用策略,因为随着策略的增加,它会创建太多的类。
发布于 2015-08-10 23:11:16
尝试使用AOP。AspectJ允许您定义切入点(例如,一些过滤的方法集),并通过建议(在方法调用之前、之后、周围)控制它们的执行:
@Aspect
class ClassName {
...
@PointCut("call(public void ClassName.*(..))") //includes all void methods of ClassName object
public void myPointCut(){}
@Around("myPointCut()")
public void myLogicMethod(ProceedingJoinPoint thisJoinPoint) {
if(shouldGetExecuted1(context.getXXX())){
thisJoinPoint.proceed()
}
}
}
在这里,thisJoinPoint.proceed()
将执行被拦截方法的主体。
阅读有关如何定义切入点的文档。在本例中,同样的逻辑将应用于该类的所有void方法。您可以通过特殊表达式定义更精确的切入点,从而为每个切点提供不同的逻辑。
发布于 2015-08-10 23:03:21
不,在Java中没有干净的方法可以做到这一点。您可以使用反射找到方法,但是无法找到诸如"availableDataN“这样的变量。因此,您必须将"availableDataN“作为一个字段,以便使用反射找到它。
最后的代码将像以下所示的那样丑陋:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class X {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Method shouldGetExecuted = X.class.getMethod("shouldGetExecuted" + i, String.class);
boolean b = (boolean) shouldGetExecuted.invoke(null, context.getXXX());
if (b) {
Method tranformDataForField = X.class.getMethod("tranformDataForField");
Field data = X.class.getField("availableData" + i);
Object result = tranformDataForField.invoke(null, data.get(null));
Method set = X.class.getMethod("setField" + i, TransformDataType.class);
set.invoke(null, result);
}
}
}
}
你需要适应你的具体情况。例如,这里假设所有字段和方法都是静态的。如果它们不是,则需要用实例引用替换null。
发布于 2015-08-11 16:25:14
如果您在命名方法时是一致的,那么反射可能会有很大帮助。
以下代码假设如下:
Document
类,包含像xxx
或xxYy
这样的字段(getter/setter通常会出现,但代码不需要)Transformer
的类shouldTransformXxx(context)
。Document
中的相应字段相同)。这些方法被命名为T transformXxx(T)
。
DataProvider
类。这些方法被命名为findXxx()
下面的代码是非常乐观的--如果任何字段的shouldTransformXxx
失败,或者如果它返回true,则findXxx
和transformXxx
方法也会失败。因此,您必须创建每个方法都有100个方法的类,这对我来说似乎不太理想。但另一方面,拥有100名成员的班级似乎会导致尴尬的局面。
下面是代码:
public class Document {
private String name;
private int size;
@Override
public String toString() {
return "Document [name=" + name + ", size=" + size + "]";
}
}
public class Transformer {
public enum ContextType {
NAME, SIZE
}
public boolean shouldTransformName(Set<ContextType> context) {
return context.contains(ContextType.NAME);
}
public boolean shouldTransformSize(Set<ContextType> context) {
return context.contains(ContextType.SIZE);
}
public String transformName(String name) {
return "::" + name;
}
public int transformSize(int size) {
return size + 1;
}
}
public class DataProvider {
private final String name;
private final int size;
public DataProvider(String name, int size) {
this.name = name;
this.size = size;
}
public String findName() {
return name;
}
public int findSize() {
return size;
}
}
public class Main {
private static final String TRANSFORM_METHOD_PREFIX = "transform";
private static final String CHECK_METHOD_PREFIX = "shouldTransform";
private static final String DATAPROVIDER_METHOD_PREFIX = "find";
private final DataProvider dataProvider;
private final Transformer transformer;
public Main(DataProvider dataProvider, Transformer transformer) {
this.dataProvider = dataProvider;
this.transformer = transformer;
}
public Document transformFields(Set<ContextType> context)
throws ReflectiveOperationException {
Document document = new Document();
for (Field field : Document.class.getDeclaredFields()) {
String capitalizedfieldName = capitalize(field.getName());
Class<?> fieldType = field.getType();
if (shouldTransform(context, capitalizedfieldName)) {
Object data = findData(capitalizedfieldName);
Object transformed = transformData(capitalizedfieldName,
fieldType, data);
// in presence of a security manager, a reflective call of the
// setter could be performed
field.setAccessible(true);
field.set(document, transformed);
}
}
return document;
}
private Object transformData(String capitalizedfieldName,
Class<?> fieldType, Object data)
throws ReflectiveOperationException {
String methodName = TRANSFORM_METHOD_PREFIX + capitalizedfieldName;
Method method = Transformer.class.getMethod(methodName, fieldType);
return method.invoke(transformer, data);
}
private Object findData(String capitalizedfieldName)
throws ReflectiveOperationException {
String methodName = DATAPROVIDER_METHOD_PREFIX + capitalizedfieldName;
Method method = DataProvider.class.getMethod(methodName);
return method.invoke(dataProvider);
}
private boolean shouldTransform(Set<ContextType> context,
String capitalizedfieldName) throws ReflectiveOperationException {
String methodName = CHECK_METHOD_PREFIX + capitalizedfieldName;
Method method = Transformer.class.getMethod(methodName, Set.class);
return (Boolean) method.invoke(transformer, context);
}
private String capitalize(String fieldName) {
char upperCaseFirstChar = Character.toUpperCase(fieldName.charAt(0));
if (fieldName.length() > 1) {
return upperCaseFirstChar + fieldName.substring(1);
} else {
return Character.toString(upperCaseFirstChar);
}
}
public static void main(String[] args) throws ReflectiveOperationException {
DataProvider dataProvider = new DataProvider("sample", 1);
Set<ContextType> context = EnumSet.of(ContextType.NAME,
ContextType.SIZE);
Main main = new Main(dataProvider, new Transformer());
Document document = main.transformFields(context);
System.out.println(document);
}
}
https://stackoverflow.com/questions/31930321
复制相似问题