ホームページ > Java > &#&チュートリアル > 動的プロキシを介して Java で単純なインターセプタ操作を実装する方法

動的プロキシを介して Java で単純なインターセプタ操作を実装する方法

王林
リリース: 2023-04-30 20:55:05
転載
931 人が閲覧しました

1. プロキシ

動的プロキシを使用してインターセプタを実装する前に、まず Java プロキシとは何かを簡単に理解しましょう。

エージェントは、その名前が示すように、プロキシされるオブジェクト (以下、ターゲット オブジェクトと呼びます。この方がわかりやすいでしょう) を直接操作するのではなく、プロキシ オブジェクトを通じて間接的にターゲット オブジェクト内のメソッドを使用します。エージェントは 2 つのモードに分けられ、1 つは静的エージェント、もう 1 つは動的エージェントです。次に、静的プロキシの例を作成します。

静的プロキシでも動的プロキシでも、ターゲット オブジェクト (target) はインターフェイス (interface) を実装する必要があります。ただし、cglib が提供するプロキシを使用する場合は、インターフェイスを実装する必要はありませんですが、サブクラスを介して実装されているため、このメソッドについては今のところ説明しません。

(1) まずインターフェイスを定義します

public interface IUserDao {
    void save();
}
ログイン後にコピー

(2) ターゲット オブジェクト (target) を定義します

public class UserDaoImpl implements IUserDao {
    public void save() {
        System.out.println("--------已经保存数据---------");
    }
}
ログイン後にコピー

(3) プロキシ オブジェクトを定義します

public class UserDaoProxy implements IUserDao {
 private IUserDao target;//将目标对象放到代理对象中
 public UserDaoProxy(IUserDao target){
  this.target = target;
  }
 public void save() {
     System.out.println("------开始事务------");
            target.save();
     System.out.println("-------提交事务------");
    }
}
ログイン後にコピー

次のテスト:

public class Test {
public static void main(String[] args){
    IUserDao userDao = new UserDaoImpl();
    UserDaoProxy proxy = new UserDaoProxy(userDao);
    proxy.save();//通过代理对象调用save方法
    }
}
ログイン後にコピー

出力結果は次のとおりです:

------トランザクションの開始------
--------データは保存されました --------

----------トランザクションのコミット-----

#このメソッドには問題がありますつまり、プロキシ オブジェクトは、プロキシ オブジェクトによって実装されるのと同じインターフェイスを実装する必要があり、深刻な結合につながります。したがって、以下では、動的プロキシ (jdk プロキシ) という改良された方法が使用されます。

動的プロキシ メソッドでは、ターゲット オブジェクト (target) にもインターフェイスを実装する必要があります。

(1) インターフェイス (IUserDao) を定義します。

(2) ターゲット オブジェクトを定義します。 class (UserDaoImpl )

(3) 動的プロキシ クラスを作成します

public class ProxyFactory {
    //维护一个目标对象
    private Object target; 
    public ProxyFactory(Object target) {
        this.target = target;
    }
 
    //给目标对象生成代理对象
    public Object getProxyInstance() {
        System.out.println("----target class---" + target.getClass());
        System.out.println("----target interfaces---" +
            target.getClass().getInterfaces());
 
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                    System.out.println("----开始事务2-----");
 
                    //执行目标对象方法
                    Object returnValue = method.invoke(target, args);
                    System.out.println("----提交事务2----");
 
                    return returnValue;
                }
            });
    }
}
ログイン後にコピー
テストします:

public class Test {
    public static void main(String[] args) {
        //目标对象
        IUserDao target = new UserDao();
        System.out.println(target.getClass());
 
        //给目标对象创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
        System.out.println("----proxy----:" + proxy.getClass());
        proxy.save();
        proxy.delete();
    }
}
ログイン後にコピー
出力結果:

class com. jd.pattern.proxy.dynamicProxy.UserDao

----ターゲット クラス---クラス com.jd.pattern.proxy.dynamicProxy.UserDao
----ターゲット インターフェイス---[Ljava.lang.クラス;@1fb3ebeb
----プロキシ----: クラス com.sun.proxy.$Proxy0
----トランザクション 2 を開始-----
-----保存完了--- ---
----トランザクション 2 を送信-----
----トランザクション 2 を開始-----
----削除完了 ----

------トランザクション 2 を送信------

2. 動的プロキシを使用して単純なインターセプタを実装する

動的プロキシ メソッドが使用されるため、インターフェイス、ターゲット クラス、プロキシ クラス、およびインターセプターになります。

1. インターフェイスを定義します

public interface BusinessFacade {
    void doSomething();
}
ログイン後にコピー

2. ターゲット オブジェクトを定義します

public class BusinessClass implements BusinessFacade {
    public void doSomething() {
        System.out.println("在业务组件BusinessClass中调用doSomething方法");
    }
}
ログイン後にコピー

3. インターセプターを作成します

public class InterceptorClass {
    public void before() {
        System.out.println("在InterceptorClass中调用方法:before()");
    }
 
    public void after() {
        System.out.println("在InterceptorClass中调用方法:after()");
    }
}
ログイン後にコピー

4. プロキシを作成します

public class DynamicProxyHandler {
    //声明被代理对象
    private Object target;
    //创建拦截器
    InterceptorClass interceptor = new InterceptorClass();
    //动态生成一个代理对象,并绑定被代理类和代理处理器
    public Object getProxyInstance(final Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                    interceptor.before();
                    Object result = method.invoke(target, args);
                    interceptor.after();
                    return result;
                }
            });
    }
}
ログイン後にコピー

テストします:

public class Test {
    public static void main(String[] args) {
        //创建动态代理工具
        DynamicProxyHandler proxyHandler = new DynamicProxyHandler();
        //创建业务组件
        BusinessFacade target = new BusinessClass();
        //获取代理对象
        BusinessFacade proxy = (BusinessFacade) proxyHandler.getProxyInstance(target);
        //通过代理对象调用目标对象方法
        proxy.doSomething();
    }
}
ログイン後にコピー
出力結果:

InterceptorClass のメソッドを呼び出します: before()

ビジネス コンポーネント BusinessClass の doSomething メソッドを呼び出します。
InterceptorClass のメソッドを呼び出します: after()

以上が動的プロキシを介して Java で単純なインターセプタ操作を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート