0

実際、これは質問ではありませんが、本当にあなたの意見が必要です... あなたがいつもアクティブであることを知っているので、彼の投稿をここに置きました。

私は Java 動的プロキシを使用して集中化しました。スタンドアロン モードで使用した JPA のコードです。動的プロキシ コードは次のとおりです。

package com.forat.service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import com.forat.service.exceptions.DAOException;

/**
 * Example of usage :
 * <pre>
 * OnlineFromService onfromService = 
 *            (OnlineFromService) DAOProxy.newInstance(new OnlineFormServiceImpl());
 *        try {
 *            Student s = new Student();
 *            s.setName("Mohammed");
 *            s.setNationalNumber("123456");
 *            onfromService.addStudent(s);    
 *        }catch (Exception ex) {
 *            System.out.println(ex.getMessage());
 *        }
 *</pre>
 * @author mohammed hewedy
 *
 */
public class DAOProxy implements InvocationHandler{

    private Object object;
    private Logger logger = Logger.getLogger(this.getClass().getSimpleName());

    private DAOProxy(Object object) {
        this.object = object;
    }

    public static Object newInstance(Object object) {
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), 
                    object.getClass().getInterfaces(), new DAOProxy(object));
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        EntityManagerFactory emf = null;
        EntityManager em = null;
        EntityTransaction et = null;
        Object result = null;
        try {
            emf = Persistence.createEntityManagerFactory(Constants.UNIT_NAME);
            em = emf.createEntityManager();;
            Method entityManagerSetter = object.getClass().
                getDeclaredMethod(Constants.ENTITY_MANAGER_SETTER_METHOD, EntityManager.class);
            entityManagerSetter.invoke(object, em);
            et = em.getTransaction();
            et.begin();
            result = method.invoke(object, args);
            et.commit();
            return result;
        }catch (Exception ex) {
            et.rollback();
            Throwable cause = ex.getCause();
            logger.log(Level.SEVERE, cause.getMessage());
            if (cause instanceof DAOException)
                throw new DAOException(cause.getMessage(), cause);
            else
                throw new RuntimeException(cause.getMessage(), cause);
        }finally {
            em.close();
            emf.close();
        }
    }
}

詳細情報を含むリンクは次のとおりです ( http://m-hewedy.blogspot.com/2010/04/using-dynamic-proxies-to-centralize-jpa.html )

それでは、ご意見をお聞かせください。

ありがとう。

4

2 に答える 2

1

つまり、トランザクション境界ロジックを1つの場所にカプセル化し、動的プロキシを使用して、トランザクション管理で既存のサービスを強化し、定型コードを削減しましたね。

音は私にはかなり大丈夫に聞こえます。実際、宣言型トランザクションの境界について話すときに、SpringやEJBなどのコンテナーが行うことは非常に似ています。実装に関しては、動的プロキシやバイトコードインストルメンテーションを使用して実行したり、AspectJを使用したりすることもできます。小さなテストフレームワークに対して、私は一度非常に似たようなことをしました。これについてのブログ投稿があります。

私が見るトリッキーな部分は次のとおりです。

1)ロールバックのみ。JPA仕様に従って、エンティティトランザクションは「ロールバックのみ」としてフラグを立てることができます。そのようなトランザクションは決してコミットできません。したがって、これら2つの行の間で次のことを確認する必要があると思います。

result = method.invoke(object, args);
et.commit();

2)再入可能。宣言型トランザクションを持つほとんどのシステムは、まだアクティブなトランザクションがない場合にのみトランザクションが開始されるセマンティクスを実装します(このEJBアノテーションのリストの「必須」を参照)。isActiveロジックでそれを確認する必要があるようです。

3)例外処理。動的プロキシでの例外の伝播には十分注意してください。プロキシは、クライアントに対して可能な限り透過的であると想定されています。DAOからリークする以外の例外が発生した場合DAOException、プロキシはそれをに変換しRuntimeExceptionます。私には最適に聞こえません。また、失敗したために例外を混同しないでください。またinvoke、呼び出しによってラップされた例外は、そのまま再スローする必要があると思います。

catch ( InvocationTargetException e )
{
     Throwable nested = e.getTargetException();
     throw nested;
}

結論:このシナリオで動的プロキシを使用するという考えは、私には問題ないように思えます。ただし、コードを再確認する必要があるものがいくつかあると思います(JPA仕様と動的プロキシでの例外処理の詳細をすべて覚えているわけではありませんが、注意が必要な場合があります)。この種のコードは微妙なバグを隠すことができるので、防弾にするのに時間をかける価値があります。

于 2010-05-12T09:28:36.327 に答える
0

過去に似たようなものを使用しましたが、hibernate API にコーディングされています (これは JPA 以前でした)。ほとんどのタイプの DAO のデータ アクセスは、オブジェクト タイプにちなんで名付けられたインターフェイスによって管理されていました。たとえば、Customer インスタンスを管理するための CustomerPersistence です。名前付きクエリにマッピングされた findXXX などのメソッドは、メソッド内のパラメータ名がクエリ内のパラメータにマッピングされます。

インターフェイスの実装はプロキシであり、インターフェイス名、メソッド名、パラメーター名などを使用して、休止状態 API で適切なメソッドを呼び出しました。

基礎となるデータアクセスフレームワークへの直感的なマッピングにより、多くのボイラープレートコーディングを節約し、データアクセスレイヤーの非常に簡単なモックを作成します.

したがって、私は間違いなくプロキシの使用に「賛成」です。

于 2010-05-07T14:14:29.413 に答える