Java AnnotationとProcessorを使用すると、メソッドを一度しか呼び出せないようにマークすることができます。

2回以上呼び出された場合にRuntimeExceptionをスローするようにメソッドをマークする必要があります。

私はいくつかの単一の代入セマンティクスを強制しようとしています。クラスへのパラメータの数が大きすぎるため、単一のコンストラクタに入れることができず、これらのクラスをJAXB にも認識させる必要があります。オブジェクトは変更可能である必要がありますが、私は単一の割り当てのセマンティクスを強制したいと思います。

私はAspectsを使ってこれを行うことができると確信していますが、代わりに自分のAnnotationsプロセッサを使用できるようにしたいと考えています。

私はPythonでDecoratorsでこれを行う方法を知っています。

コンパイル時だけでなく、実行時に注釈付きメソッドへの呼び出しを傍受できるアノテーションプロセッサを作成するにはどうすればよいですか?

Dynamic Proxiesを使ってメソッド呼び出しを傍受していると思うので、Annotationプロセッサとの統合方法を理解するだけです。

動的プロキシでは、インターフェイスを使用する必要があります。これは面倒です。 CGLib MethodInterceptor これで、インターセプトやデコレーションに必要な要件が大幅に少なくなりました依存関係を追加する費用。

5
注釈には何の振る舞いもありません。それは単なるメタデータであり、一部のツールやフレームワークで使用されることを意図しています。注釈の存在を探し、あなたが望むことをする側面を持つことができますが、注釈だけでは何もしません。
追加された 著者 JB Nizet,

4 答え

いいえ、すぐに使用できるものはありません。 AspectJはより一般的な方法で動作させる唯一の方法と思われます。 JB Nizetが指摘しているように、注釈には解析するためのパーサーが必要です。

しかし、私はより良い、より簡単なソリューション - Builderパターンをお勧めします。それはどのように見えるのですか?

  • you have a FooBuilder (it may also be a static inner class) which is mutable and has a setter and getter for each of the fields
  • FooBuilder has a build() method that returns an instance of Foo
  • Foo has a constructor that takes only FooBuilder, and you assign each field there.

その方法:

  • Foo is immutable, which is your end goal
  • It is easy to use. You only set the fields that you need. Something like:

    Foo foo = new Foo.FooBuilder().setBar(..).setBaz(..).build();
    

ビルダーはJAXBを認識できるようになります。例えば:

FooBuilder builder = (FooBuilder) unmarshaller.unmarshal(stream);
Foo foo = builder.build();

JAXBオブジェクトは変更可能である必要があり、要件は不変オブジェクトです。したがって、ビルダーはそれを橋渡しするのに便利です。

3
追加された
@ Jarrod Robersonは私が最後に追加した段落を見ています
追加された 著者 Bozho,
ビルダーパターンはJAXBアノテーションでは機能しません
追加された 著者 feeling unwelcome,
ビルダーパターン+1
追加された 著者 Philipp Wendler,
@Bozho、私はビルダーのものをバイパスする傾向があり、フラグ "configured"とassertConfigurable()をミューテータに追加します。後でミューテータを有効にする必要がある場合(たとえばJMX)、アサーションを削除するだけです。ビルダーパターンの複製はちょっと面倒です。
追加された 著者 bestsss,
うわー、私はそれが私が特定のプロジェクトに必要なものかもしれないと思います!
追加された 著者 G_H,

この質問は、アノテーションプロセッサからのCGLibプロキシの適用の質問と類似しています。 。

注釈プロセッサで元のソースコードの動作を変更できるようにするには、 http:// projectlombok .org/はこれを実現します。唯一の欠点は、lombokはcom.sun。*クラスに依存していることです。

私はこのようなものを自分で必要とするので、これを達成するためのより良い方法を誰かが知っていて、まだアノテーションプロセッサを使用しているのだろうかと思います。

2
追加された

@XmlAccessorType(XmlAccessType.FIELD)を使用してフィールド(インスタンス変数)アクセスを使用するようにJAXBを設定できます。これにより、setメソッドで必要なことを行うことができます:

JAXBの XmlAdapter メカニズムを使用して、不変オブジェクトをサポートすることもできます。

1
追加された

注釈を使用する代わりに、使用することができます。

assert count++ != 0;

メソッドごとに1つのカウンタが必要です。

0
追加された
それは維持するためのいくつかの厄介なコードでしょう
追加された 著者 feeling unwelcome,
実行時に一度呼び出されるメソッドをチェックすることは厄介な要件です。
追加された 著者 Peter Lawrey,
@bestsss、もしあなたが好きなら、あなたは私を0に連れてくることができます。
追加された 著者 Peter Lawrey,
私はアサーションのアプローチを承認します。なぜなら、余分なシンプルな解決策があるとき(なぜかファンキーなものを学ぶ必要はない)、人々がなぜ「フレームワーク」からあまりにも多くを期待しているのか、
追加された 著者 bestsss,
@ピーター、...しかし、私は何もそれをしない場合、私は投票する50賞金を与えることができます
追加された 著者 bestsss,
デフォルトでは@G_H、 java -enableassertions [: ... |:] (または -ea
追加された 著者 bestsss,
@G_H、アサーションは、定数の折りたたみの最適化のためにランタイムコストがゼロになるという利点があります...
追加された 著者 bestsss,
しかし、私はアサーションが実行時に無効になっていると思います。私はかつていくつかを使用して、彼らが間違っていることを私が彼らがデフォルトでオンではないことを思い出させるまで渡すことを見て驚いた。あなたのアプローチは、IllegalStateExceptionのような単純なランタイム例外をスローするだけです。
追加された 著者 G_H,
@bestsssコードがどこでどのように使用されているかを制御できると仮定すると、うまくいくでしょう。それはそうでないかもしれません。また、アサーションは、コードが期待どおりに機能しているかどうかを確認するのに優れていますが、コードが適切に使用されているかどうか、つまりメソッドが一度だけ呼び出されるかどうかの問題です。だから、私は実行時の例外をスローし、あなたのコードを使用して(ab)それを受け入れることを許可すると信じています。それではまた、それは実際にアサーションが何をするのかです...とにかく、実際にはまともな提案だから+1してください。
追加された 著者 G_H,
興味深い@bestsss、それを知らなかった!そのようなマイナーな最適化が設計上の決定に影響を与えてはならないと言っていたのですが、どれだけ多くの方法を適用するのかは誰にも分かりません。
追加された 著者 G_H,