Javaでプロパティを動的に追加する

免責事項


このツールは小さな血の設計上の欠陥を克服する方法として生まれました。 楽器の使用が他の理由によって決定される状況を想像することはほとんどできません。



背景


ある日、中年のWebアプリケーションの開発に接続しました。 コードはいくつかの場所でかなり乱雑で、さまざまな資格を持つ複数の開発者の活動の痕跡を残しており、実際の機能テストはありませんでした。 一つの言葉はレガシーです。

アプリケーションは、従来の3層スキームに従って実装されました。



また、すべてのレベルで、ストレージレベルのエンティティ(以下、エンティティと呼びます)が使用されました。 このため、エンティティのプロパティの名前を変更するには、クライアントまたはJSPでコードを編集する必要があり、コントローラーが提供したJSONまたはJSPに何かを追加する必要がありました。テストの欠如。



エンティティにない値を表現のレベルにドラッグする方法は?


いくつかの方法を検討しました。



リスナーとインターセプター


リスナーインターセプターを使用すると、エンティティに追加のデータを追加できます。 場合によっては、それらの使用は正当化されますが、ストレージレベルのエンティティを、ストレージレベルとは関係のない構造やデータで詰まらせたくないです。



マッピング


拡張を必要とする各クラスから継承し、サービスレベルで既に必要なデータを使用して開始できます。 これは概念的に正しいパスです。ストレージレイヤーはクリーンに保たれ、コントローラーレイヤーは変更する必要がありません。 ただし、パフォーマンスの問題があり、 遅延読み込み遅延しなくなります。 マッパーはコントローラーが必要とするフィールドを認識せず、すべてを強制的にシフトします。 コントローラー側からマッパーを制御することは理論的には可能ですが、これはコントローラーコードを変更しない限り不可能です。



動的プロキシ


ちょっとした魔法:

package ru.bdm.reflection; //some imports omitted import static junit.framework.Assert.assertEquals; import static org.apache.commons.beanutils.PropertyUtils.getProperty; public class PropertyJoinerTest { public static class AnyType { public Object getAnyProperty() { return "anyPropertyValue"; } } @Test public void testWithPropertyExtractor() throws Exception { PropertyJoiner propertyJoiner = new PropertyJoiner(new PropertyExtractor() { @Override public Object get(Object o, String property) { return property + "Value"; } }, "first", "second"); AnyType src = new AnyType(); AnyType dst = propertyJoiner.joinProperties(src); assertEquals("firstValue", getProperty(dst, "first")); assertEquals("secondValue", getProperty(dst, "second")); assertEquals("anyPropertyValue", getProperty(dst, "anyProperty")); } }
      
      





フードの下には何がありますか?


追加プロパティのインターフェイスクラスは動的に作成されます。

 public interface FirstHolder{ Object getFirst(); } public interface SecondHolder{ Object getSecond(); }
      
      





AnyType



を継承し、 AnyType



およびAnyType



を実装するプロキシクラスが動的に作成されます。

AnyType



で定義されたAnyType



src



にリダイレクトされるプロキシ、 FirstHolder



およびSecondHolder



定義されたメソッドは、追加のプロパティを計算するロジックを含むPropertyExtractor



にリダイレクトされます。



したがって、コントローラーのコードを変更することなく、ストレージレベルの本質を外部の構造やデータで詰まらせることなく、遅延読み込みの問題によるパフォーマンスの低下を招くことなく、ビューを拡張する機会を得ました。



これに対する料金はそれほど高くありませんでした。プロキシを介したプロパティへのアクセスは、直接よりも約150倍遅くなります。 これは、ツールを使用するときに考慮する必要があります。

アプリケーションの負荷は1秒あたり数件のリクエストのみで、リクエストごとに最大50のエンティティ(ページサイズ)が読み込まれたため、プロキシの損失の割合は無視できました。



Googleドライブからコードをダウンロードできます。



All Articles