Dev Study
← Spring コース

38. 動的プロキシ

は、指定した(持つべきだけを書いた型)を実装するを、実行時に作る 標準の仕組みです。そのに対するインターフェースのメソッドの呼び出しは、toString、equals、hashCode と合わせて、という1つの関数に届きます。ハンドラの中で本物のメソッドを呼べば、その前後にログ出力などの処理を挟めます。呼び出す側のコードは変わりません。

包み役のクラスを手で書いても同じことはできますが、インターフェースごと、メソッドごとに書くことになります。なら1つのハンドラで済みます。ハンドラには呼ばれたメソッドの情報が渡るので、前のレッスンのと同じ道具で扱えます。 がこの仕組みをどう使っているかは、後のレッスンで扱います。

つまずきどころはです。下のコードで placeOrder の中から this.audit() を呼ぶと、ハンドラを通りません。ハンドラが取り次いだ先は本物のオブジェクトで、その中の this はプロキシではないからです。また対象はインターフェースに限られ、クラスを渡すとになります。作られるクラスの名前は仕様では未規定で、この実測では $Proxy0 でした。

点線の付いた語はタップすると説明が出ます。用語集を開く →

プロキシ越しの呼び出しと、自己呼び出し
呼び出す側svc.placeOrder()
OrderService 型として呼ぶ
プロキシ実行時に作られたクラスのインスタンス
インターフェースのメソッドの呼び出しはここに届く
ハンドラ前後に処理を挟み、本物へ取り次ぐ
method.invoke(real, args)
本物の placeOrder()この中の this は本物
本物の audit()this.audit() は直接ここへ。ハンドラを通らない
  • ・Javadoc は「The unqualified name of a proxy class is unspecified.」と書いています。$Proxy0 という名前は実測値で、インターフェースが public のときは jdk.proxy1.$Proxy0 になりました(JDK 25)
  • ・自己呼び出しがハンドラを通らないことは Javadoc の規則ではなく、ハンドラが本物へ取り次ぐ、という書き方から出てくる結果です
  • ・ハンドラに届くのはインターフェースのメソッドと toString・equals・hashCode です。getClass など、Object から受け継いだそれ以外のメソッドは届きません(Javadoc)

▶ サンプルコードを実行してみよう(自由に書き換えてOK)

Java

図やコードに出てくる用語(タップで説明)

サンプルコードで身につける(5本) →

学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。

公式ドキュメントで詳しく ↗