2009-06-01 6 views

答えて

13

私は非常にresourceこれをお勧めします。

まず、プロキシパターンの使用例を理解する必要があります。プロキシの主な目的は、 ターゲットオブジェクトの機能を拡張するのではなく、 ターゲットオブジェクトへのアクセスを制御することです。アクセス制御には、同期、認証、リモートアクセス(RPC)、遅延インスタンス化(Hibernate、Mybatis)、AOP(トランザクション)が含まれます。

動的プロキシとは異なり、動的プロキシは実行時にJavaリフレクションを必要とするバイトコードを生成します。動的では、プロキシクラスを作成する必要がなくなり、利便性が向上します。

+0

とリンクが壊れています – bvdb

+0

リンクのおかげで...非常に助けて本当に。 – worked

+0

これは最高の答えだと思います。他の答えには、私の人生では決して理解できない、非常に難しい設定が含まれています。リンクはちょっとステップごとに私を助けてくれました。 – SWIIWII

8

クラスjava.lang.reflect.ProxyあなたはInvocationHandlerでメソッド呼び出しを処理することにより、動的にインタフェースを実装することができます。これはJavaのリフレクション機能の一部とみなされますが、バイトコードの生成とは関係ありません。

日は、Proxyクラスの使用についてa tutorialを持っています。 Google helps, too.

5

つのユースケースは、休止状態である - それはあなたのモデルクラスのインタフェースを実装するオブジェクトを提供しますが、ゲッターとセッターの下にあり、DB関連のコードを常駐します。私。彼らは単純なPOJOであるかのようにそれらを使用しますが、実際には多くのことがカバーされています。例えば

- あなただけの遅延ロードプロパティのゲッターを呼び出し、本当に財産(おそらく全体の大きなオブジェクト構造)がデータベースからフェッチ取得します。

詳しくはcglibライブラリをチェックしてください。

28

動的プロキシクラスは、別のクラスのインスタンスのインターフェイスの 一方を介してメソッド呼び出しは、符号化され、 がディスパッチされるように、実行時に指定された インタフェースのリストを実装するクラスであります均一なインターフェースを介してオブジェクトプロキシクラスの事前生成を必要とせずに、インターフェイス のリストのためのタイプセーフなプロキシオブジェクトを作成するために使用される にすることができます。ダイナミックプロキシ クラスは、 インタフェースAPIを提示するオブジェクトに対して 型呼び出しを安全に反映させるために、アプリケーションまたはライブラリに役立ちます。

Dynamic Proxy Classes

+0

丁寧な答えは、HTTP、RMI、EJB、およびJMS用のプロキシ機能を備えたSpring Remotingです。 – Robin

16

私は、動的プロキシのための興味深い使用を思い付きました。

我々はいくつかの問題、別の依存サービスと結合し、その依存サービスが利用できなくなったときにフォールトトレラントであることの方法を模索したい非クリティカルなサービスを持ちました。 1は、(JNDIルックアップの後)「通常の」サービス用のリモートIMPLある -

だから私は2つのデリゲートを取る LoadSheddingProxyを書きました。もう1つのオブジェクトは、「ダミー」ロード・セッティング・インプットです。タイムアウトをキャッチし、再試行する前に一定時間ダミーに転用する各メソッド呼び出しを囲む単純なロジックがあります。ここでは、私はそれを使用する方法は次のとおりです。

// This is part of your ServiceLocator class 
public static MyServiceInterface getMyService() throws Exception 
{ 
    MyServiceInterface loadShedder = new MyServiceInterface() { 
     public Thingy[] getThingys(Stuff[] whatever) throws Exception { 
      return new Thingy[0]; 
     } 
     //... etc - basically a dummy version of your service goes here 
    }   
    Context ctx = JndiUtil.getJNDIContext(MY_CLUSTER); 
    try { 
     MyServiceInterface impl = ((MyServiceHome) PortableRemoteObject.narrow(
       ctx.lookup(MyServiceHome.JNDI_NAME), 
       MyServiceHome.class)).create(); 
     // Here's where the proxy comes in 
     return (MyService) Proxy.newProxyInstance(
      MyServiceHome.class.getClassLoader(), 
     new Class[] { MyServiceInterface.class }, 
     new LoadSheddingProxy(MyServiceHome.JNDI_NAME, impl, loadShedder, 60000)); // 10 minute retry 
    } catch (RemoteException e) { // If we can't even look up the service we can fail by shedding load too 
     logger.warn("Shedding load"); 
     return loadShedder; 
    } finally { 
     if (ctx != null) { 
     ctx.close(); 
     } 
    } 
} 

そして、ここでは、プロキシです:

public class LoadSheddingProxy implements InvocationHandler { 

static final Logger logger = ApplicationLogger.getLogger(LoadSheddingProxy.class); 

Object primaryImpl, loadDumpingImpl; 
long retry; 
String serviceName; 
// map is static because we may have many instances of a proxy around repeatedly looked-up remote objects 
static final Map<String, Long> servicesLastTimedOut = new HashMap<String, Long>(); 

public LoadSheddingProxy(String serviceName, Object primaryImpl, Object loadDumpingImpl, long retry) 
{ 
    this.serviceName = serviceName; 
    this.primaryImpl = primaryImpl; 
    this.loadDumpingImpl = loadDumpingImpl; 
    this.retry = retry; 
} 

public Object invoke(Object obj, Method m, Object[] args) throws Throwable 
{ 
    try 
    { 
     if (!servicesLastTimedOut.containsKey(serviceName) || timeToRetry()) { 
      Object ret = m.invoke(primaryImpl, args); 
      servicesLastTimedOut.remove(serviceName); 
      return ret; 
     } 
     return m.invoke(loadDumpingImpl, args); 
    } 
    catch (InvocationTargetException e) 
    { 
     Throwable targetException = e.getTargetException(); 

     // DETECT TIMEOUT HERE SOMEHOW - not sure this is the way to do it??? 
     if (targetException instanceof RemoteException) { 
      servicesLastTimedOut.put(serviceName, Long.valueOf(System.currentTimeMillis())); 
     } 
     throw targetException; 
    }      
} 

private boolean timeToRetry() { 
    long lastFailedAt = servicesLastTimedOut.get(serviceName).longValue(); 
    return (System.currentTimeMillis() - lastFailedAt) > retry; 
} 
} 
関連する問題