【小知識】程式碼優化-動態新增大量擴充套件欄位

noname發表於2022-01-31

背景

接手一個老專案的統計介面,統計最近21周的資料,返回的結果是一組陣列:

[
    {"A欄位": "A1值", "B欄位": "B1值", "week1": 1, "week2": 1, "week3": 2, ......, "week21": 3 },
    {"A欄位": "A2值", "B欄位": "B2值", "week1": 5, "week2": 3, "week3": 12, ......, "week21": 7 },
    ......
]

封裝的結果物件是:

public class StatRetClass {
    private String A欄位;
    private String B欄位;
    private Integer week1;
    private Integer week2;
    ......
    private Integer week21;
}

後來業務改為統計最近27周的資料,於是類又改為:

public class StatRetClass {
    private String A欄位;
    private String B欄位;
    private Integer week1;
    private Integer week2;
    ......
    private Integer week21;
    private Integer week22;
    private Integer week23;
    private Integer week24;
    private Integer week25;
    private Integer week26;
    private Integer week27;
}

之後又多次修改,最近一次改為79周,每次修改,都要寫上大量的weekX欄位,以及對應的get&set方法(也可以用lombok)。
那麼是否有方法可以在儘量少修改程式碼的情況下,支援對統計週數的調整。

方案

weekX欄位不硬編碼,而是在建立物件時,動態新增。
這裡使用了cglib來動態生成屬性。
首先將統計的週數量提取為配置變數WEEKCOUNT,方便通過配置系統動態修改值。

public static <T extends StatRetClass> T buildCompareModelDto(Class<T> clazz) {
    Map<String, Class> propertyMap = Maps.newHashMap();
    IntStream.range(0, WEEKCOUNT).forEach(i -> {
        propertyMap.put("week" + (i + 1), Integer.class);
    });
    BeanGenerator generator = new BeanGenerator();
    generator.setSuperclass(clazz);
    BeanGenerator.addProperties(generator, propertyMap);
    return (T) generator.create();
}

原先的new StatRetClassSub1()new StatRetClassSub2()分別改為StatRetClass.buildCompareModelDto(StatRetClassSub1.class)StatRetClass.buildCompareModelDto(StatRetClassSub2.class)

另:cglib生成的屬性名固定帶有$cglib_prop_字首,但是get&set方法沒有帶字首。例如生成的week1屬性名是$cglib_prop_week1,但是get方法是getWeek1()

相關文章