从Java类生成方面

时间:2011-03-23 11:56:33

标签: java code-generation aspectj

我正在寻找一种在构建过程中从Java类生成aspectJ方面的方法。 目标是生成一个类型间声明方面,其中包含java类的每个属性的String常量。

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知道maven等工具或插件可以实现此行为?

由于

马丁

4 个答案:

答案 0 :(得分: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 Basic编写模板) )

由于 -Blake Niemyjski(CodeSmith员工)

答案 1 :(得分:1)

也许您可以尝试注释处理。见apt:

http://download.oracle.com/javase/1.5.0/docs/guide/apt/GettingStarted.html

Eclipse和AspectJ识别完整和增量构建中的注释处理。

答案 2 :(得分:1)

那么, 最后我得到了一个解决方案,但仍然陷入困境。 apt的暗示是成功的。

我设法创建了一个AnnotationProcessor,它生成一个方面作为String。这就是问题所在。创建一个新的File对象并将String粘贴到其中为每个带注释的类创建方面文件是不是很糟糕? 这是我目前可以成像的唯一方式。

感谢

马丁

<强>解决方案:

我创建了一个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";
    }
}

另外,您必须在

中创建配置文件
META-INF/services

称为

javax.annotation.processing.Processor

包含包和AnnotationProcessor的名称

my.package.annotation.processor.DTOConstantAnnotationProcessor

最后,maven构建过程中的include:

   <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

多数人=)

答案 3 :(得分:0)

AspectJ Version 1.8.2现在支持Annotation Processing。您可以使用此功能在构建过程中生成ApspectJ文件,由某些注释触发。

请参阅此博客文章以获取示例: http://andrewclement.blogspot.de/2014/08/annotation-processing-in-ajdt.html