2011-03-23 56 views
2

我正在尋找一種方法來在構建過程中生成Java類中的aspectJ方面。 目標是生成一個類型間聲明方面,該類型聲明方面爲java類的每個屬性包含一個String常量。從Java類生成方面

Java類:

public class CarDTO { 

    private String vendor; 
    private String name; 


    public String getVendor() {} 
    public String getName() {} 
    [..]  
} 

這是應該生成方面:

aspect CarAspect 
{ 
    public static final String CarDTO.VENDOR = "vendor"; 
    public static final String CarDTO.NAME = "name"; 
} 

是否有任何obne知道的工具或行家等插件有,我可以實現這種行爲?

感謝

馬丁

+0

,那豈不是更好地你的getter和setter移入方面呢? – 2011-03-23 19:57:23

+0

好吧,沒有。我們在後端代碼中使用getter和setter。因此它更容易直接在DTO中。防止編譯錯誤=) – martin 2011-03-30 07:18:25

回答

1

那麼, 最後我得到了一個解決方案,但仍然卡住在一個點。 與apt的提示是成功的。

我設法創建了一個AnnotationProcessor,它以String的形式生成一個方面。這是問題。創建一個新的File對象並將其粘貼到其中以創建每個註釋類的方面文件是不好的? 那是我目前可以成像的唯一方法。

感謝

馬丁

解決方案:

我創造了我的創建方面的AnnotationProcessor(JDK1.6)。 generateAspect方法在每個方面的默認源輸出文件夾中創建一個文件。

@SupportedAnnotationTypes({ "my.own.annotation.GenerateDTOConstants" }) 
@SupportedSourceVersion(SourceVersion.RELEASE_6) 
public class DTOConstantAnnotationProcessor extends AbstractProcessor { 

    private static final Logger LOG = LoggerFactory 
      .getLogger(DTOConstantAnnotationProcessor.class); 

    private static final String ASPECT_POSTFIX = ".aj"; 


    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 

     DTOConstantElementVisitor visitor = new DTOConstantElementVisitor(); 
     for(TypeElement element : annotations) { 

      Set<? extends Element> annotatedClasses = roundEnv.getElementsAnnotatedWith(element); 

      for(Element dto : annotatedClasses) { 
       generateAspect(visitor, dto); 
      } 
     } 

     return true; 

    } 

    /** 
    * @param visitor 
    * @param dto 
    */ 
    private void generateAspect(DTOConstantElementVisitor visitor, Element dto) { 
     dto.accept(visitor, null); 
     LOG.info("Generating aspect for " + dto.getSimpleName()); 

     Filer filer = this.processingEnv.getFiler(); 
     try { 

      String fileName = visitor.getFileName() + ASPECT_POSTFIX; 
      String pkg = visitor.getPkg(); 

      FileObject aspectFile = filer.createResource(StandardLocation.SOURCE_OUTPUT, pkg, 
        fileName); 

      Writer writer = aspectFile.openWriter(); 
      LOG.info("writing aspect content into file"); 
      writer.write(visitor.getFileContent()); 

      writer.close(); 
      LOG.info("Aspect generated for " + visitor.getFileName()); 
     } 
     catch(IOException e) { 
      e.printStackTrace(); 
      throw new java.lang.RuntimeException(e); 
     } 
    } 
} 

答案這裏是我使用的訪問者(只是一個片段):

public class DTOConstantElementVisitor extends AbstractElementVisitor6<Void, String> { 

    private static final String FIELD_PREFIX = "public static final String "; 

    private String fileName = null; 

    private String clazzName; 
    private String pkg; 

    private StringBuffer fileContentBuff; 

    @Override 
    public Void visitPackage(PackageElement e, String p) { 
     System.out.println("visitPackage" + e); 

     return null; 
    } 

    @Override 
    public Void visitType(TypeElement e, String p) { 
     System.out.println("visitTypeElement" + e); 

     try { 
      Class<?> clazz = Class.forName(e.getQualifiedName().toString()); 
      this.clazzName = clazz.getSimpleName(); 
      createFileName(clazz); 

      this.pkg = clazz.getPackage().getName(); 
      this.fileContentBuff = new StringBuffer(); 

      fileContentBuff.append("package " + this.pkg + ";\n"); 
      fileContentBuff.append("public aspect " + this.fileName + " {\n"); 

      for(Field field : clazz.getDeclaredFields()) { 
       if(Modifier.isPrivate(field.getModifiers())) { 
        String fieldName = field.getName(); 

        if(shouldGenerateField(fieldName)) { 
         fileContentBuff.append(FIELD_PREFIX + clazzName + "." 
           + fieldName.toUpperCase() + " = \"" + fieldName + "\";\n"); 
        } 

       } 
      } 
      fileContentBuff.append("}\n"); 

      System.out.println(fileContentBuff.toString()); 

     } 
     catch(ClassNotFoundException e1) { 
      throw new java.lang.RuntimeException(e1); 
     } 

     return null; 
    } 
    private boolean shouldGenerateField(String fieldName) { 
     if("serialVersionUID".equals(fieldName)) { 
      return false; 
     } 
     return true; 
    } 

    private void createFileName(Class clazz) { 
     this.fileName = clazzName + "Aspect"; 
    } 
} 

Additonally你必須建立在

META-INF/services 

配置文件名爲

javax.annotation.processing.Processor 

包含包和n在AnnotationProcessor

my.package.annotation.processor.DTOConstantAnnotationProcessor 

最後,包括在Maven構建過程的AME:

<build> 
    <plugin> 
     <groupId>org.bsc.maven</groupId> 
     <artifactId>maven-processor-plugin</artifactId> 
     <version>2.0.0</version> 
     <executions> 
      <execution> 
      <id>aspectprocessing</id> 
      <phase>compile</phase> 
      <goals> 
        <goal>process</goal> 
      </goals> 
      </execution> 
     </executions> 
    </plugin> 
    </build> 

爲奮鬥目標,單呼使用

mvn processor:process 

這就是所有=)

+0

至於你對每個訪問類的一個方面的問題:我認爲在單個方面收集多個ITD語句不會有問題。你只需要限制每個方面生成的代碼,以防萬一你有很多類。 – kriegaex 2014-11-11 21:32:02

1

您可以生成這種代碼CodeSmith Generator。如果您在Visual Studio內部使用JScript(Microsoft),則可以使用我們的GenerateOnBuild or MSBuildsee this document aswell)支持。否則,你可以在你的構建過程中將CodeSmith Generator可執行文件放到shell中,並讓它生成代碼。

需要構建自定義模板來解析文件並生成代碼。開箱即用,我們支持Parsing Visual Basic or CSharp Code Files並從Visual Basic或CSharp生成(這對您沒有任何幫助,但會向您顯示它已完成並受到支持)。這裏有一些documentation on creating a custom template。我也知道你可以拿compiled jar file and convert it to a .NET assembly。從這裏你可以在模板中使用reflection並生成你的Java代碼。

這可能不是最好的選擇,因爲你沒有集成Eclipse(取決於你的編輯器,但它是一個可以很容易地解決這個問題的替代解決方案)你也可以用JScript,CSharp或Visual編寫你的模板基本)

感謝 -Blake Niemyjski(CodeSmith的員工)