6

クラスが不変であるために必須であることを目的としたアノテーションに取り組んでいます。ここにプロセッサのコードがあります:

@SupportedAnnotationTypes("archipel.immutability.IsImmutable")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class IsImmutableProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        for (TypeElement type : annotations) {
            processMustBeImmutable(roundEnv, type);
        }
        return true;
    }

    private void processMustBeImmutable(RoundEnvironment env, TypeElement type) {
        for (Element element : env.getElementsAnnotatedWith(type)) {
            processClass(element);
        }
    }

    private void processClass(Element element) {
        boolean isFinal=false;

        for(Modifier modifier : element.getModifiers()) {
            if (modifier.equals(Modifier.FINAL)) {
                isFinal=true;
                break;
            }
        }

        if (!isFinal) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Class "+element+" is not immutable because it is not final");
        } else {
            for (Element subElement : element.getEnclosedElements()) {
                if (subElement.getKind()==ElementKind.FIELD) {
                    isFinal=false;

                    for(Modifier modifier : subElement.getModifiers()) {
                        if (modifier.equals(Modifier.FINAL)) {
                            isFinal=true;
                            break;
                        }
                    }
                    if (!isFinal) {
                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Field "+element+" is not immutable because it is not final");
                    } else {
                        Element superElement = subElement.getEnclosingElement();
                        // TODO
                    }
                }
            }
        }
    }

}

もちろん、注釈自体は簡単です。

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface IsImmutable {
}

そして、Antスクリプトを使用してコンパイルします。

<project name="immutability" basedir="." default="main">

    <property name="lib.dir" value="lib"/>

    <property name="src.dir" value="src"/>

    <property name="build.dir" value="build"/>
    <property name="classes.dir" value="${build.dir}/classes"/>
    <property name="meta.dir" value="${build.dir}/META-INF"/>
    <property name="jar.dir" value="${build.dir}/jar"/>

    <property name="processor-package"
        value="archipel.immutability" />

    <property name="processor" value="${processor-package}.IsImmutableProcessor"/>

    <path id="classpath">
        <fileset dir="${lib.dir}" includes="**/*.jar"/>
        <fileset dir="${classes.dir}"/>
    </path>

    <target name="clean">
    <delete dir="${build.dir}"/>
    </target>

    <target name="compile" description="Compiles the code.">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" />
    </target>

    <target name="jar" depends="compile">
        <mkdir dir="${jar.dir}"/>
        <jar destfile="${jar.dir}/${ant.project.name}.jar">
            <fileset dir="${classes.dir}"/>
            <service type="javax.annotation.processing.Processor" provider="archipel.immutability.IsImmutableProcessor"/>
        </jar>
    </target>

    <target name="main" depends="clean,jar"/>

</project>

問題は、次のように、結果のjarファイルによって提供される結果のアノテーションを使用しようとすると、何も起こらないため、何かが欠落している必要があることです。

@IsImmutable
public class Immut {

    private int toto;

    public int getToto() {
        return toto;
    }

    public void setToto(int toto) {
        this.toto = toto;
    }

    public final static void main(String args[]) {
        Immut truc = new Immut();
        truc.setToto(5);
        truc.setToto(6);
    }

}

明らかに、このクラスは最終的なものではなく、クラスはEclipseでエラーを通知する必要があります。しかし、そうではありません。

何か案が?

編集:build.xmlで作成したjarファイルは正しいようです:クラスファイルとMETA-INF/services/javax.annotation.processing.Processor、を含むファイルが含まれていますarchipel.immutability.IsImmutableProcessor。このjarファイルをテストプロジェクトにインポートしましたが、Immutクラスでアノテーションを使用しても(これは大まかなテストにすぎません)、何も起こりません。

4

2 に答える 2

11

Eclipseでは、注釈処理はデフォルトで無効になっています。これを有効にするには、プロジェクトのプロパティを開いてから、1。Javaコンパイラ->アノテーション処理:アノテーション処理を有効にする2.Javaコンパイラ->アノテーション処理->ファクトリパス:工場でjarを追加する

さらに詳しい情報が必要な場合は、以下を参照してください:EclipseでAPを使い始める

編集:

このチュートリアルを見てください。カスタムアノテーションプロセッサを使用するようにEclipseを設定する方法について詳しく説明します。

重要:印刷エラー の場合は、次javax.annotation.processing.Messager.printMessage(Kind, CharSequence, Element) の代わりに次の方法を使用してください。
javax.annotation.processing.Messager.printMessage(Kind, CharSequence).

最初のメッセージからのメッセージは問題ビューとほとんどのソース関連ビューに表示されますが、2番目のメッセージからのメッセージはErrorLogビューにのみ表示されます。

于 2012-07-21T19:24:40.160 に答える
0

おそらく、オブジェクトを不変にするためにcglibを使用する価値があります。クラス内にコレクションがあり、コレクションフィールドが最終的なものであると想像してください。このコレクションのゲッターもあります。クラス外でコレクションを変更できないということですか?ではない正確に。このコレクションがCollections.unmodifiedCollectionメソッドでラップされている場合のみ。または、グアバ不変コレクションを使用している場合http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained

重要なのは、フィールドが最終的なものかどうかをチェックするだけでこれを処理しようとしないでください。すべてのシナリオを処理できるわけではありません。springやhibernateのように代わりにcglibプロキシを使用してください

于 2012-07-27T13:13:10.977 に答える