Создать аспект из класса Java - PullRequest
2 голосов
/ 23 марта 2011

Я ищу способ генерировать аспект 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";
}

Кто-нибудь знает об инструменте или плагине для maven и т. Д., С помощью которого я могу добиться такого поведения?

Спасибо

1017 * мартин *

Ответы [ 4 ]

1 голос
/ 23 марта 2011

Возможно, вы можете попробовать обработку аннотаций. Смотрите квартиру:

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

Eclipse и AspectJ распознают обработку аннотаций как в полной, так и в инкрементальной сборках.

1 голос
/ 25 марта 2011

Ну, наконец-то я нашел решение, но все же застрял в одной точке.Подсказка к 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";
    }
}

У вас есть добавлениесоздать файл конфигурации в

META-INF/services

с именем

javax.annotation.processing.Processor

, который содержит пакет и имя AnnotationProcessor

my.package.annotation.processor.DTOConstantAnnotationProcessor

И, наконец, включить вПроцесс сборки Maven:

   <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

Вот и все =)

1 голос
/ 23 марта 2011

Вы можете сгенерировать этот код с помощью CodeSmith Generator .Если вы используете JScript (Microsoft) внутри Visual Studio , вы можете использовать нашу поддержку GenerateOnBuild или MSBuild (, см. Также этот документ ).В противном случае вы можете обработать исполняемый файл CodeSmith Generator изнутри вашего процесса сборки и заставить его генерировать код таким же образом.

Необходимо будет создать собственный шаблон для анализа файла и генерации кода.Из коробки мы поддерживаем парсинг файлов кода Visual Basic или CSharp и генерацию из Visual Basic или CSharp (это не полезно для вас, но показывает, что это было сделано и поддерживается).Вот некоторая документация по созданию пользовательского шаблона .

Также я знаю, что вы можете взять скомпилированный файл jar и преобразовать его в сборку .NET .Отсюда вы можете использовать отражение в шаблоне и генерировать свой Java-код.

Это может быть не лучшей альтернативой, поскольку у вас нет интеграции с Eclipse (в зависимости от вашего редактора, но этоЭто альтернативное решение, которое может легко решить эту проблему. Также вы можете написать свой шаблон в JScript, CSharp или Visual Basic)

Спасибо -Blake Niemyjski (Сотрудник CodeSmith)

0 голосов
/ 11 ноября 2014

AspectJ версии 1.8.2 теперь поддерживает обработку аннотаций.Вы можете использовать эту функцию для создания файлов ApspectJ во время процесса сборки, вызванного некоторыми аннотациями.

См. Этот пост в блоге для примера: http://andrewclement.blogspot.de/2014/08/annotation-processing-in-ajdt.html

...