JAVAダイナミックエージェント(JDKとCGLIB)
8852 ワード
JAVAの動的エージェントモードエージェントモードはよく使われるjava設計モードであり、エージェントクラスは依頼クラスと同じインタフェースを持つことを特徴とし、エージェントクラスは主に依頼クラスのためにメッセージを前処理し、メッセージをフィルタリングし、メッセージを依頼クラスに転送し、事後処理メッセージなどを担当する.エージェントクラスと委任クラスの間には通常関連関係があり、1つのエージェントクラスのオブジェクトと1つの委任クラスのオブジェクトが関連しており、エージェントクラスのオブジェクト自体はサービスを実装するのではなく、委任クラスのオブジェクトの関連メソッドを呼び出すことで、特定のサービスを提供します.エージェントの作成時期によって、エージェントクラスは2つに分けることができます.静的エージェント:プログラマによって作成または特定のツールによってソースコードが自動的に生成され、コンパイルされます.プログラムの実行前にエージェントクラスの.classファイルはすでに存在します.動的エージェント:プログラムの実行時に、反射メカニズムを用いて動的に作成されます.
まず静的エージェントを見てみましょう:1、Count.java
2、CountImpl.java
3、TestCount.java
コードを観察すると、各エージェントクラスは1つのインタフェースにしかサービスできないことがわかります.これにより、プログラム開発では必然的に多くのエージェントが生成されます.また、すべてのエージェント操作は呼び出しの方法が異なる以外は、他の操作は同じであり、この場合、世代コードが繰り返されるに違いありません.この問題を解決する最善の方法は、1つのエージェントクラスですべてのエージェント機能を完了できるようにすることです.この場合、動的エージェントを使用して完了する必要があります.動的エージェント:JDK動的エージェントにはクラスとインタフェースが含まれています:InvocationHandlerインタフェース:public interface InvocationHandler{public Object invoke(Object proxy,Method,Object[args])throws Throwable;}パラメータの説明:Object proxy:エージェントされるオブジェクトを指します.Method method:呼び出すメソッドObject[]args:メソッド呼び出しに必要なパラメータ
InvocationHandlerインタフェースのサブクラスをエージェントの最終操作クラスとして想像し,ProxySubjectを置き換えることができる.
Proxyクラス:Proxyクラスはエージェントを専門とする操作クラスであり、1つ以上のインタフェースに対して動的に実装クラスを生成することができます.これには、public static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h)throws I llegalArgumentExceptionパラメータの説明:ClassLoader loader:クラスローダClass[]interfaces:すべてのインタフェースを取得InvocationHandler h:InvocationHandlerインタフェースのサブクラスインスタンスを取得する
Ps:Proxyクラス内のクラスローダのnewProxyInstance()メソッドにはClassLoaderクラスのインスタンスが必要です.ClassLoaderは実際にはクラスローダに対応しています.Javaには主に3種類のローダがあります.Booststrap ClassLoader:このローダはC++で記述されています.一般開発では見られません.Extendsion ClassLoader:拡張クラスのロードに使用されます.一般的にはjrelibextディレクトリのクラスに対応しています.AppClassLoader:(デフォルト)classpathで指定されたクラスをロードし、最もよく使用されるのはローダです.
動的エージェントは静的エージェントクラスと対照的に動的エージェントクラスであり,動的エージェントクラスのバイトコードはプログラム実行時にJava反射メカニズムによって動的に生成され,プログラマが手動でソースコードを記述する必要はない.動的エージェントクラスはプログラミング作業を簡素化するだけでなく、Java反射メカニズムが任意のタイプの動的エージェントクラスを生成できるため、ソフトウェアシステムの拡張性を向上させる.java.lang.reflectパッケージのProxyクラスとInvocationHandlerインタフェースは、動的エージェントクラスを生成する能力を提供します.
動的エージェントの例:1、BookFacade.java
2、BookFacadeImpl.java
3、TestProxy.java
しかし,JDKの動的エージェントはインタフェースに依存して実現され,クラスによってはインタフェースが実装されていない場合,JDKエージェントは使用できないため,cglib動的エージェントが使用される.
Cglib動的エージェントJDKの動的エージェントメカニズムはエージェントがインタフェースを実現したクラスのみをエージェントすることができ、インタフェースを実現できないクラスはJDKの動的エージェントを実現することができず、cglibはクラスに対してエージェントを実現し、彼の原理は指定した目標クラスに対してサブクラスを生成し、その中国側法をカバーして強化を実現することであるが、継承を採用しているため、だからfinal修飾のクラスをエージェントすることはできません.例1、BookFacadeCglib.java
2、BookCadeImpl1.java
3、BookFacadeProxy.java
4、TestCglib.java
まず静的エージェントを見てみましょう:1、Count.java
package net.battier.dao;
/**
*
*
* @author Administrator
*
*/
public interface Count {
//
public void queryCount();
//
public void updateCount();
}
2、CountImpl.java
package net.battier.dao.impl;
import net.battier.dao.Count;
/**
* ( )
*
* @author Administrator
*
*/
public class CountImpl implements Count {
@Override
public void queryCount() {
System.out.println(" ...");
}
@Override
public void updateCount() {
System.out.println(" ...");
}
}
、CountProxy.java
package net.battier.dao.impl;
import net.battier.dao.Count;
/**
* ( CountImpl )
*
* @author Administrator
*
*/
public class CountProxy implements Count {
private CountImpl countImpl;
/**
*
*
* @param countImpl
*/
public CountProxy(CountImpl countImpl) {
this.countImpl = countImpl;
}
@Override
public void queryCount() {
System.out.println(" ");
// ;
countImpl.queryCount();
System.out.println(" ");
}
@Override
public void updateCount() {
System.out.println(" ");
// ;
countImpl.updateCount();
System.out.println(" ");
}
}
3、TestCount.java
package net.battier.test;
import net.battier.dao.impl.CountImpl;
import net.battier.dao.impl.CountProxy;
/**
* Count
*
* @author Administrator
*
*/
public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
コードを観察すると、各エージェントクラスは1つのインタフェースにしかサービスできないことがわかります.これにより、プログラム開発では必然的に多くのエージェントが生成されます.また、すべてのエージェント操作は呼び出しの方法が異なる以外は、他の操作は同じであり、この場合、世代コードが繰り返されるに違いありません.この問題を解決する最善の方法は、1つのエージェントクラスですべてのエージェント機能を完了できるようにすることです.この場合、動的エージェントを使用して完了する必要があります.動的エージェント:JDK動的エージェントにはクラスとインタフェースが含まれています:InvocationHandlerインタフェース:public interface InvocationHandler{public Object invoke(Object proxy,Method,Object[args])throws Throwable;}パラメータの説明:Object proxy:エージェントされるオブジェクトを指します.Method method:呼び出すメソッドObject[]args:メソッド呼び出しに必要なパラメータ
InvocationHandlerインタフェースのサブクラスをエージェントの最終操作クラスとして想像し,ProxySubjectを置き換えることができる.
Proxyクラス:Proxyクラスはエージェントを専門とする操作クラスであり、1つ以上のインタフェースに対して動的に実装クラスを生成することができます.これには、public static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h)throws I llegalArgumentExceptionパラメータの説明:ClassLoader loader:クラスローダClass[]interfaces:すべてのインタフェースを取得InvocationHandler h:InvocationHandlerインタフェースのサブクラスインスタンスを取得する
Ps:Proxyクラス内のクラスローダのnewProxyInstance()メソッドにはClassLoaderクラスのインスタンスが必要です.ClassLoaderは実際にはクラスローダに対応しています.Javaには主に3種類のローダがあります.Booststrap ClassLoader:このローダはC++で記述されています.一般開発では見られません.Extendsion ClassLoader:拡張クラスのロードに使用されます.一般的にはjrelibextディレクトリのクラスに対応しています.AppClassLoader:(デフォルト)classpathで指定されたクラスをロードし、最もよく使用されるのはローダです.
動的エージェントは静的エージェントクラスと対照的に動的エージェントクラスであり,動的エージェントクラスのバイトコードはプログラム実行時にJava反射メカニズムによって動的に生成され,プログラマが手動でソースコードを記述する必要はない.動的エージェントクラスはプログラミング作業を簡素化するだけでなく、Java反射メカニズムが任意のタイプの動的エージェントクラスを生成できるため、ソフトウェアシステムの拡張性を向上させる.java.lang.reflectパッケージのProxyクラスとInvocationHandlerインタフェースは、動的エージェントクラスを生成する能力を提供します.
動的エージェントの例:1、BookFacade.java
package net.battier.dao;
public interface BookFacade {
public void addBook();
}
2、BookFacadeImpl.java
package net.battier.dao.impl;
import net.battier.dao.BookFacade;
public class BookFacadeImpl implements BookFacade {
@Override
public void addBook() {
System.out.println(" 。。。");
}
}
、BookFacadeProxy.java
package net.battier.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK
*
* @author student
*
*/
public class BookFacadeProxy implements InvocationHandler {
private Object target;
/**
*
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); // ( ,cglib )
}
@Override
/**
*
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
System.out.println(" ");
//
result=method.invoke(target, args);
System.out.println(" ");
return result;
}
}
3、TestProxy.java
package net.battier.test;
import net.battier.dao.BookFacade;
import net.battier.dao.impl.BookFacadeImpl;
import net.battier.proxy.BookFacadeProxy;
public class TestProxy {
public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
}
しかし,JDKの動的エージェントはインタフェースに依存して実現され,クラスによってはインタフェースが実装されていない場合,JDKエージェントは使用できないため,cglib動的エージェントが使用される.
Cglib動的エージェントJDKの動的エージェントメカニズムはエージェントがインタフェースを実現したクラスのみをエージェントすることができ、インタフェースを実現できないクラスはJDKの動的エージェントを実現することができず、cglibはクラスに対してエージェントを実現し、彼の原理は指定した目標クラスに対してサブクラスを生成し、その中国側法をカバーして強化を実現することであるが、継承を採用しているため、だからfinal修飾のクラスをエージェントすることはできません.例1、BookFacadeCglib.java
package net.battier.dao;
public interface BookFacade {
public void addBook();
}
2、BookCadeImpl1.java
package net.battier.dao.impl;
/**
*
*
* @author student
*
*/
public class BookFacadeImpl1 {
public void addBook() {
System.out.println(" ...");
}
}
3、BookFacadeProxy.java
package net.battier.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* cglib
*
* @author student
*
*/
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
*
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
//
enhancer.setCallback(this);
//
return enhancer.create();
}
@Override
//
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println(" ");
proxy.invokeSuper(obj, args);
System.out.println(" ");
return null;
}
}
4、TestCglib.java
package net.battier.test;
import net.battier.dao.impl.BookFacadeImpl1;
import net.battier.proxy.BookFacadeCglib;
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}