2014-02-05 119 views
13

我想找到一個問題的最佳解決方案,我已經映射了一個簡單的bean結構發送到基於瀏覽器的JavaScript應用程序。目前的需求是管理舊Java後端的大部分顯示控件。目前,我們正在生產的值對象內置了無顯示的邏輯服務作風層,如:複雜的豆映射

public class Example1 { 
    String value1; 
    Boolean value2; 
    Example3 value3; 

    public String getValue1(){...} 
    public void setValue1(){...} 
    .... 
} 

我的目標是能夠到一個通用的結構在這樣所有字段映射,它增加了新的顯示結構這是前端所需要的。我想僅管理原始結構類(Example1類)結構,並簡單地將包裝中的額外值設置爲舊的服務層。

通用結構將採取以下類的形式:

public class Presentable<T> { 
    T value; 
    boolean visible = true; 
    boolean mandatory = false; 
    List<String> errors = new ArrayList<>(); 

    public T getValue() {...} 
    public void setValue(T value) {...} 
    ... 
} 

最終的結果將類似於以下,其中值是在原結構相同的價值:

public class Example2{ 
    Presentable<String> value1; 
    Presentable<Boolean> value2; 
    Presentable<Example3> value3; 

    public Presentable<String> getValue1(){...} 
    public void setValue1(){...} 
    ... 
} 

有沒有解決這個問題,而不寫一個Example2風格的類,並在每一個值複製?我願意修改Example1類,因爲它不會影響舊服務的使用者。

謝謝。

+0

更新:我發現的唯一解決方案是使用帶有註釋的代碼生成。雖然我確實寫了一個快速工作的POC,但它很髒。 –

+0

根據客戶需求,您需要擁有Example1的多個對象。那麼爲什麼你需要一個通用的類。您可以使用前端數組列表映射,所以每當用戶添加一個新數組時,它就會自動在ArrayList中添加另一個Example1對象,您將擁有一個列表,其中包含example1的所有對象。 – Dileep

回答

4

你可以基本上使用AOP(Aspect Oriented Programming)和Spring。在春天,您可以創建一個包含所需額外信息的代理對象。 良好的出發點是: http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/

上面向方面編程官方頁面: http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/aop.html

這個例子/答案可能是有用的: Intercepting method with Spring AOP using only annotations

+0

這與我正在尋找的內容很接近,但Spring並不是一種選擇,儘管我確實意識到大多數Enterprise Java應用程序現在都合併了Spring。 –

1

所以我不知道如果我理解正確的您。然而...

這是一個我們可以很容易地使用反射的地方。

對於我們班Example1.class我們調用getDeclaredMethods,getDeclaredFields(在簡單的用例)或的getMethods,在更復雜的(簡單的POJO,但繼承)getFields。例如,您可能需要一些簡單的邏輯來刪除static修飾符或類似的字段。

對於每個方法/領域,我們得到適當的方法/字段從Example2.class與getMethod(字符串名稱)或getfield命令(字符串名稱)

通過現場或setter設置我們的價值,新的對象。如果私人等修飾符存在問題,我們使用setAccessible。

簡單的使用情況下,一些代碼:

public Example2 decorateWithWrapper(Example1 obj) { 
    Example2 wrapped = new Example2(); 
    for (Field field : obj.getClass().getDeclaredFields()) { 
     Field toAssign = wrapped.getClass().getField(field.getName()); 
     toAssign.setAccessible(true); 
     toAssign.set(wrapped, field.get(obj)); 
    } 
    return wrapped; 
} 

這是很容易,如果需要從這個上面做的比較通用的方法。

您不需要任何外部庫或工具。

1

您可以使用傑克遜ObjectMapper和配置[Dozer][1]映射做這個複雜的豆映射,讓JSON應用&瀏覽器之間的通信。

Dozer可讓您將字段一次映射到其他字段。爲Dozer映射基本代碼如下所示:

<mappings>   
    <mapping> 
    <class-a>org.dozer.vo.TestObject</class-a> 
    <class-b>org.dozer.vo.TestObjectPrime</class-b> 
    <!-- Any custom field mapping xml would go here --> 
    </mapping> 
</mappings> 

在此,在上述例子中,的TestObject所有變量被映射到TestObjectPrime。對於你的情況,你需要自定義映射到這個配置,如下表現:

<mapping> 
    <class-a>org.dozer.vo.deep.SrcDeepObj</class-a> 
    <class-b>org.dozer.vo.deep.DestDeepObj</class-b> 

    <field> 
    <a>srcNestedObj.src1</a> 
    <b>dest1</b> 
    </field> 

    <field> 
    <a>srcNestedObj.src2</a> 
    <b>dest2</b> 
    </field> 

    <field> 
    <a>srcNestedObj.srcNestedObj2.src5</a> 
    <b>dest5</b> 
    </field> 

    <field><!-- java.util.List to java.util.List --> 
    <a>srcNestedObj.hintList</a> 
    <b>hintList</b> 
    <a-hint>java.lang.String</a-hint>   
    <b-hint>java.lang.Integer</b-hint> 
    </field> 

    <field> 
    <a>srcNestedObj.hintList2</a> 
    <b>hintList2</b> 
    <a-hint>org.dozer.vo.TheFirstSubClass</a-hint> 
    <b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint> 
    </field> 

    <field copy-by-reference="true"> 
    <a>srcNestedObj.hintList3</a> 
    <b>hintList3</b> 
    </field-deep> 

</mapping> 

隨着推土機教程說:

它可以映射深性質。一個例子是當你 有一個String屬性的對象。您的其他對象具有字符串 屬性,但它在對象圖中位於幾個級別深處。在下面的 示例中,DestDeepObj在對象 圖中具有需要映射的嵌套屬性。深度字段 映射支持類型提示。還可以使用關係類型copy-by-reference,type = one-way和 relationship-type。

以上示例摘自推土機documentation

Shishir

0

要啓用AspectJ時,你需要aspectjrt.jar,aspectjweaver.jar彈簧aop.jar。 對於我們的類Example1.class,我們調用getDeclaredMethods,getDeclaredFields(簡單用例)或getMethods,getFields更復雜(簡單pojo但帶繼承)。