我有一个名为Document.java的POJO,包含100多个成员变量。有一个转换层,我获取所需的数据,转换它并将其存储在Document类中。
在转换层中,我想仅在满足某个条件(基于可用上下文)时才设置成员变量。
所以它看起来像这样:
if(shouldGetExecuted1(context.getXXX())){
document.setField1(tranformDataForField1(availableData1));
}
if(shouldGetExecuted2(context.getXXX())){
document.setField2(tranformDataForField2(availableData2));
}
我想为所有100多个领域做这件事。有干净的方法吗?
其他信息
我不想在这里使用策略,因为它会创建太多的课程,因为策略的增长不会。
答案 0 :(得分:1)
尝试使用AOP。 AspectJ允许您定义切入点(例如,一些过滤的方法集)并通过 advices 控制它们的执行(在方法之前电话,在之后,在周围):
@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方法。您可以通过特殊表达式定义更准确的切入点,为每个切入点提供不同的逻辑。
答案 1 :(得分:0)
不,在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替换为实例引用。
答案 2 :(得分:0)
如果您对方法的命名保持一致,那么反思可能会有很大帮助。
以下代码假定以下内容:
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);
}
}