[セットトップ]Javaの動的エージェント


前言
    プログラミングを学ぶには設計モードが欠かせない.設計モードにはエージェントモードがあり、最初はJavaの学習において、このような重要な地位を占めていることを知らなかったが、設計モードだと思っていただけで、どのように使うか考えたことがない.その後,エージェントモデルがAOP実現の重要な原理であることが分かった.
JDKの動的エージェント
    JDKの動的エージェントは、インタフェースを使用するクラスをエージェントし、実際のロールとエージェントロールが必要です.JDKダイナミックエージェントはjava.lang.reflectパッケージの2つのクラス:ProxyとInvocationHandlerに関連します.ここでInvocationHandlerはインタフェースであり,AOPはこのインタフェースを実現することによって横断論理を定義し,反射機構によってターゲットクラスを呼び出し,横断コードを動的にトラフィック論理に切り込む.Proxyは、InvocationHandlerによってインタフェースに一致するインスタンスを動的に作成し、ターゲットクラスのプロキシオブジェクトを生成します.
    JDKの動的エージェントクラスはInvocationHandlerインタフェースを実装し,このクラスには2つのメソッド1つのオブジェクトがある.このオブジェクトはクラスプライベートで、呼び出されたターゲットクラスオブジェクトを表します.Proxyクラスで作成されたプロキシインスタンスを新規作成し、このターゲットインスタンスをターゲットクラスオブジェクトに割り当て、最後にinvokeメソッドを呼び出します.もう一つの方法はinvoke方法であり,この方法はエージェントクラスの論理,すなわちエージェントクラスがしなければならないことである.
public class SecurityHandler implements InvocationHandler {
	//          
	private Object targetObject;
	//        
	public Object createProxyInstance(Object targetObject) {
		this.targetObject = targetObject;
		return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
							   targetObject.getClass().getInterfaces(), 
							   this);
	}
	//        
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		checkSecurity();
		
		//      ,         
		Object ret = method.invoke(targetObject, args);
		
		return ret;
	}
	//         
	private void checkSecurity() {
		System.out.println("-------checkSecurity-------");
	}		
}

            
Proxyクラスでプロキシインスタンスを作成する場合は、プロキシされたクラスとプロキシクラスで実装されたインタフェース、作成されたインスタンスオブジェクトの3つのパラメータを入力する必要があります.入力パラメータから分かるように,JDKの動的エージェントは,実装インタフェースのクラスに対してのみエージェントクラスを作成できる.
//         
public interface UserManager {

	public void addUser(String username, String password);
	
	public void delUser(int userId);
	
	public String findUserById(int userId);
	
	public void modifyUser(int userId, String username, String password);
}
//    
public class UserManagerImpl implements UserManager {

	public void addUser(String username, String password) {
		System.out.println("---------UserManagerImpl.add()--------");
	}

	public void delUser(int userId) {
		System.out.println("---------UserManagerImpl.delUser()--------");
	}

	public String findUserById(int userId) {
		System.out.println("---------UserManagerImpl.findUserById()--------");
		return "  ";
	}

	public void modifyUser(int userId, String username, String password) {
		System.out.println("---------UserManagerImpl.modifyUser()--------");
	}
}

CGLIBの動的エージェント
    JDKの動的エージェントは実装インタフェースのクラスに対してのみエージェントクラスを作成することができますが、インタフェースを実装しないクラスは?エージェントクラスを作成するにはCGLIBが必要です.CGLIBは,実装インタフェースのないクラスに対してエージェントクラスを作成するとともに,実装インタフェースのクラスに対してCGLIB動的エージェントを強制的に使用することができる.
    CGLIBは最下位のバイトコード技術を採用し、1つのクラスにサブクラスを作成し、サブクラスでメソッドブロックの技術を採用してすべての親メソッドの呼び出しをブロックし、横断を実現することができる.
public class CglibProxy implements MethodInterceptor {
	//       
	private Enhancer enhancer = new Enhancer();
	//    
	public Object getProxy(Class class) {
		enhancer.setSuperclass(class); //          
		enhancer.setCallback(this); 
		return enhancer.create(); //               
	}

        //           
	public Object intercept(Object obj, Method method, Object[] args, 
			MethodProxy proxy) throws Throwable {
		PerformanceMonitor.begin(obj.getClass().getName()+"."+method. getName());
		Object result=proxy.invokeSuper(obj, args);
		PerformanceMonitor.end();//             
		return result;
	}
}

     getProxyメソッドを使用して、サブクラスを作成する必要があるクラスを入力し、プロキシオブジェクトenhancerのcreateメソッドを使用してサブクラスインスタンスを作成します.このプロセスはエージェントクラスのインタフェースを必要としないので,CGLIBはインタフェースを実装しないクラスのエージェントクラスを作成することができる.interceptメソッドは、親クラスのすべてのメソッドをブロックし、対応するエージェントクラスが実行する必要があるコンテンツを追加し、エージェントクラスを通じて親クラスのメソッドを呼び出します.
まとめ
    JDKダイナミックエージェントは,jarパケットを別途導入する必要はないが,CGLIBはダイナミックエージェントを実現し,CGLIBのjarパケットを導入する必要がある.一般に,インタフェースを用いたプログラミングはより柔軟であるため,JDKで実現される動的エージェントを用いることが多い.動的エージェントはAOP実装の原理であり、動的エージェントによってセキュリティチェック、ログ記録、トランザクションなどを実現することができ、これらもAOP実装の例である.一つの知識点に触れるのは、今何ができるかを制限するのではなく、発散的な思考で考え、将来何ができるか、このような訓練を多くしてこそ、知識に網を織ることができる.