2013-05-03 65 views
0

我正在提供任何人都可以在其代碼中包含的註釋@validateName。假設一些一個編碼當對象狀態發生變化時調用方法

class Person { 
    @validateName 
    private String name; 
    .... 
} 

然後,他們可以調用NameValidator.validate(personObject)或驗證該領域的一些類似的方法。

我想確保名稱字段始終處於有效狀態,即每當註釋變量發生更改時(無論其在類內部還是外部發生更改),我都會自動調用validate()方法。
我願意編寫一個掛鉤到Eclipse的插件,並在編譯階段被調用。請提供一些可以開始尋找解決方案的指南。
(我想我必須實現某種AOP的或使用中輕或東西應該修改字節碼的我不知道,因爲我還沒有用盡全力。)

+1

你有沒有考慮過使用像AspectJ這樣的AOP框架呢? – kriegaex 2013-05-03 12:24:25

回答

1

使用AspectJ,你可以這樣做:

註釋

package de.scrum_master.aop.app; 

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Retention(RetentionPolicy.RUNTIME) 
public @interface ValidateName {} 

Driver類

package de.scrum_master.aop.app; 

public class Application { 
    private int id; 
    @ValidateName 
    private String firstName; 
    @ValidateName 
    private String lastName; 
    private String placeOfBirth; 

    public Application(int id, String firstName, String lastName, String placeOfBirth) { 
     this.id = id; 
     this.firstName = firstName; 
     this.lastName = lastName; 
     this.placeOfBirth = placeOfBirth; 
    } 

    @Override 
    public String toString() { 
     return "Application [id=" + id + ", firstName=" + firstName 
       + ", lastName=" + lastName + ", placeOfBirth=" + placeOfBirth 
       + "]"; 
    } 

    public static void main(String[] args) { 
     System.out.println(new Application(1, "Galileo", "Galilei", "Pisa, Italy")); 
     System.out.println(new Application(2, "Isaac", "Newton", "Woolsthorpe-by-Colsterworth, United Kingdom")); 
     System.out.println(new Application(3, "Albert", "Einstein", "Ulm, Germany")); 
     System.out.println(new Application(4, "Werner", "Heisenberg", "Würzburg, Germany")); 
    } 
} 

驗證方面

package de.scrum_master.aop.aspect; 

import java.util.Random; 
import de.scrum_master.aop.app.ValidateName; 

public aspect NameValidator { 
    void validate(String name) { 
     if (new Random().nextBoolean()) 
      throw new RuntimeException("Invalid name " + name); 
    } 

    void around(String name) : set(@ValidateName * *.*) && args(name) { 
     //System.out.println(thisJoinPointStaticPart); 
     System.out.print("Validating name " + name); 
     try { 
      validate(name); 
      System.out.println(" -> OK"); 
      proceed(name); 
     } 
     catch (Exception e) { 
      name = name.toUpperCase(); 
      System.out.println(" -> " + e.getMessage() + " -> replaced by " + name); 
      proceed(name); 
     } 
    } 
} 

正如你所看到的,我驗證只是隨機失敗的約所有病例的50%基於僞隨機值。當它發生時,它只是用大寫的版本替換「無效的」名稱。輸出看起來像這樣的變化:

Validating name Galileo -> OK 
Validating name Galilei -> Invalid name Galilei -> replaced by GALILEI 
Application [id=1, firstName=Galileo, lastName=GALILEI, placeOfBirth=Pisa, Italy] 
Validating name Isaac -> Invalid name Isaac -> replaced by ISAAC 
Validating name Newton -> Invalid name Newton -> replaced by NEWTON 
Application [id=2, firstName=ISAAC, lastName=NEWTON, placeOfBirth=Woolsthorpe-by-Colsterworth, United Kingdom] 
Validating name Albert -> OK 
Validating name Einstein -> Invalid name Einstein -> replaced by EINSTEIN 
Application [id=3, firstName=Albert, lastName=EINSTEIN, placeOfBirth=Ulm, Germany] 
Validating name Werner -> OK 
Validating name Heisenberg -> Invalid name Heisenberg -> replaced by HEISENBERG 
Application [id=4, firstName=Werner, lastName=HEISENBERG, placeOfBirth=Würzburg, Germany] 
+0

正是!這就是我一直在尋找的!非常感謝! – sinu 2013-05-06 09:08:35

+0

我剛剛開始使用AspectJ。這個代碼在'Application.java'和方面定義是同一個項目的一部分時起作用。但是,如果我將'Application.java'放入不同的項目並將方面定義導出爲jar(我在Eclipse中導出了「帶有AspectJ支持」的'JAR文件),則AOP編織不會發生。我沒有將這個jar添加到構建路徑。但沒有幫助!任何指向我應該如何將方面定義和註釋放在一個jar中的指針,並將其用於另一個項目中的客戶端代碼? – sinu 2013-05-07 07:00:03

+0

沒關係..加入'AspectJ INPATH'解決了它:) – sinu 2013-05-07 09:01:30

相關問題