トビーのスプリングStudio(6)-OP


6.1取引コードの分離


5章ではトランザクションを処理するコードを追加した.
ユーザー・サービスで取引境界+連結ビジネス・コードを設定します.
それを分けたいです.
ユーザサービスには2つの注目点があるため,それらを分離するためには,ユーザサービス自体を実装体として抽象化する必要がある.
UserServiceをインタフェースに変更して、UserServiceのトランザクション・コードとビジネス・コードを分離します.
トランザクション・インプリメンテーション・コード(UserServiceTx)とビジネス・インプリメンテーション・コード(UserServiceImpl)が区分されています.

6.2孤立ユニットテスト


UserServiceをテストする場合、UserServiceはJDBCコード、トランザクションマネージャ、およびメールクラスに依存します.
この3つのオブジェクトも、独自のコードのみを実行するのではなく、内部に依存しています.
もしUserServiceにもっと方法があったら?あなたはもっと内部に依存します.
テストの単位は最大1つ割ったほうがいいです.
Mockオブジェクトで単位をテストします.
テストテープを作ることで、孤立したユニットテストで精密テストを行うことができ、速度も向上します.
Mockオブジェクトを直接作成するよりも、MockitoのようなMockフレームワークを使用する方が便利です

ユニットテスト、統合テスト


まず
  • ユニットテストを考慮するが、ユニットテストの作成が複雑すぎるコードについては、統合テストを考慮する.

    6.3動的エージェントと工場名


    ビジネス・コードとトランザクション・コードを分離する際に使用する方法には、設計モデルが組み込まれています.
    戦略モデルは、トランザクションの拡張性を考慮します.すなわち、トランザクションはAでもBでも構いません.
    コードには、トランザクションを適用する事実がまだ含まれています.
    完全に分離されているため、付加機能(トランザクションコード)はコア機能(ビジネスコード)を使用する構造となっている.
    コア機能は、追加機能を持つクラス自体を理解していません.
    分離は良好ですが、クライアントがコア機能を直接使用する場合は、追加機能は適用されません.
    付加機能は、自分がコア機能であるかのように、自分でコア機能を使用します.
    付加機能をエージェントと呼び,コア機能をターゲットと呼ぶ.

    装飾図案

  • ターゲット付加機能を付与するために存在する.(装飾モード)
    =>ターゲットおよびクライアント呼び出しメソッドを変更することなく、実行時に次の委任ターゲットを注入することで追加機能を追加できます.
  • 複数の追加機能は、実行時に追加して使用できます.
    トランザクションの追加機能を提供するUserServiceTXがUserServiceImplに追加され、レコーダ・モードも適用されます.

    プロキシモード

  • ターゲットに近い方法を制御します.
  • public interface Target {
    
        List<Character> unmodifiable();
    }
    
    public class TargetImpl implements Target {
    
        @Override
        public List<Character> unmodifiable() {
            List<Character> list = new ArrayList<Character>(); // 읽기전용으로 수정하고싶다.
            return list;
        }
    }
    
    クライアントは、ターゲット実装のエージェントを使用してアクセスします.
    public class Client {
    
        public static void main(String[] args) {
            Target target = new Proxy(new TargetImpl()); // 타겟구현체를 가지고 프록시로 먼저 접근한다
            List<Character> afterList = target.unmodifiable(); 
    
            /**
             * add()나 remove()메소드를 호출하면 예외발생시킨다.
             */
    
            try {
                System.out.println("add() 호출불가능");
                afterList.add('z');
            } catch (UnsupportedOperationException e) {
                System.out.println("Exception : " + e);;
            }
        }
    }
    ターゲット機能を拡張または追加しません.クライアントがターゲットにアクセスする方法を変更します.
    public class Proxy implements Target {
    
        private Target target ;
    
        public Proxy(Target target) {
            this.target  = target;
        }
        
        @Override
        public List<Character> unmodifiable() {
            List<Character> beforeList = target.unmodifiable(); // 타겟구현체로 List를 생성한다
            beforeList.add('x');
            beforeList.add('y');
            System.out.println("beforeList" + beforeList);
    
            return Collections.unmodifiableList(beforeList); // 접근권한을 제어한다.
        }
    }
    エージェントの方法でターゲットを使用しようとすると、ターゲットオブジェクトを生成する方法もあります.
    public class Client {
    
        public static void main(String[] args) {
         // Target target = new Proxy(new TargetImpl());
            Target target = new Proxy(); // 프록시로 접근
            List<Character> afterList = target.unmodifiable();
    
            /**
             * add()나 remove()메소드를 호출하면 예외발생시킨다.
             */
             
    		...
    }
    
    public class Proxy implements Target {
    
        private  Target target ;
    
        @Override
        public List<Character> unmodifiable() {
            target = new TargetImpl(); // 지연 생성
            List<Character> beforeList = target.unmodifiable(); // 타겟구현체로 List를 생성한다
    
            beforeList.add('x');
            beforeList.add('y');
            System.out.println("beforeList" + beforeList);
    
            return Collections.unmodifiableList(beforeList); // 접근권한을 제어한다.
        }
    }
    
    ターゲット機能自体はエージェントを使用してxへのアクセスを制御する
    自分がアクセスするターゲットクラス情報を知っていることが多い.
    短所
  • エージェントサーバの作成自体も動作します.
  • ターゲットのメソッドを追加する場合、エージェントはすべてのメソッドを実装し、委任し、重複コードを増加させる必要があります.
  • 追加機能コードは重複する可能性が高い.
  • ダイナミックエージェント


    JAvaには、エージェントの作成に役立つクラスがあります.
    上記の問題では、InvocationHandlerのinvoke()メソッドとしてreplicationを使用して、ターゲットインタフェース内のすべてのメソッドを処理できる2つの方法がある.
       public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
    ターゲットがInvocationHandlerを実装するオブジェクトである場合、委任コードを作成できます.
    クライアントリクエストをreplicationに変換し、invokeメソッドに渡します.
    public class TransactionHandler implements InvocationHandler{
    	private Object target;
        private PlatformTransactionManager transactionManager;
        private String pattern;
        
        Setter...
        
        
       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
       		if(method.getName().startsWith(pattern)){
            	return invokeInTransaction(method, args); // 부가기능을 적용할 대상 선별
            }else{
            	retrun method.invoke(target, args);
               
            }
       }
       
       public Object invokeInTransaction(Method method, Object[] args) throws Throwable{
       		... // 부가기능
       }
    
    }
    
    DIを使用するはずですが、空に登録することはできません.newProxyInstance()という静的ファクトリメソッドのみで作成されるためです.
    =>SpringのFactory Beanインタフェースを使用して空に設定する方法がありますが、複数のクラスに共通の追加機能を一度に提供することはできません.また、同様のエージェントファクトリ設定では重複を防止できません.

    6.4 Springの代理工場


    ProxyFactoryBeanはエージェントの作成のみを担当します.
    付加機能の追加は、MethodInterceptorインタフェースを実装することによって実現される.
    InvocationHandler実装時との違いは?
    =>ターゲットオブジェクトへの依存度は、ターゲットオブジェクトの情報を受信するかどうかによって異なります.
    ヒント:ターゲットオブジェクトに依存しない追加機能のみを含むオブジェクト
    ポイントカット:メソッド選択アルゴリズム
    ProxyFactoryBeanは、動的エージェントを作成します.
    フィルタは、機能をポイントカットでどのメソッドにアタッチするかを指定したメソッドにのみヘルプを要求します.
    ProxyFactoryBeanでは、どの機能をどこに追加するかだけに注目できます.
    ターゲットごとに追加機能を追加する問題を解決しました.

    6.5スプリングAOP


    空のポストプロセッサ
    空のオブジェクトを作成するたびに、後続の処理が実行されます.
    スプリングが空のオブジェクトを生成する場合は、代理オブジェクトとしてパッケージし、空に登録することもできます.
    ProxyFactory Beanとは異なり、DefaultAdvisor AutoProxyCreatorにはクラスとメソッドを選択できるポイントマップが必要です
    (すべての空のエージェントを自動的に適用するターゲットを選択する必要があります)
    コアコードと付加機能コード(コア機能から付加機能を分離してspectというモジュールとして設計・開発する方法)を分離するためには,オブジェクト向けの設計方法だけでは解決しにくい.
    コア機能と付加機能とともに含まれるコードは,オブジェクト指向技術の価値を低下させるため,AOP分離spectを用いることでオブジェクト指向の価値を実現するのに役立つと考えられる.

    6.6取引属性


    トランザクションAが開始および終了する前にBを呼び出すと、どのトランザクション内で動作しますか.
    トランザクション伝播プロパティは、処理されたトランザクションがどのように影響するかを定義します.
    PROPAGATION_REQUIRED
    進行中のトランザクションがない場合は再開し、ある場合は参加します.
    AとBがともにPROPACATIOnREQUIRDであれば、A、B-A->B、B->Aの4つのグループの取引が可能です.
    PROPAGATION_REQUIRES_NEW
    いつも新しい取引が始まります.前からの取引があるかどうかにかかわらず.
    PROPAGATION_NOT_SUPPORTED
    進行中の取引があっても無視されます.
    AOPを一度に使用して複数の方法を同時に使用する場合に有用である
    トランザクション・アプリケーションから除外するには、いずれかの特殊な方法のみを使用します.

    感想


    私はAOPとは何かを知っていて、私が何を言うかも知っています.
    その過程が少し深くて迷いました.
    AOPは,付加機能コードをオブジェクト指向設計手法のみでは実現しにくいコアコードから分離するモデルである.
    どうやって使えますか?
    記録に使うか、楽子を捕まえる場合に使うかもしれません.
    AOPで捕まえる必要はなく、フィルターやスクリーンで捕まえることもできますよね?
    request/responseペアをログに配置できません.aopキャプチャを推奨します.