2011-03-23 60 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的员工)