動態代理的特點是,不要靜態的寫Proxy類,而是在運行時由jdk自己幫助生成類,然后注入到classloader中去。
代碼:
public interface BusinessProcess{
void processBusiness();
}
public class BusinessProcessImpl implements BusinessProcess{
public void processBusiness(){
System.out.println("in businessProcessImpl");
}
}
如果要對BusinessProcessImpl增加權限驗證功能,那么靜態代理代碼:
public class BusinessProcessProxy implements BusinessProcess{
private BusinessProcess target;
public BusinessProcessProxy(BusinessProcess target){
this.target = target;
}
public void processBusiness(){
checkPermission();
this.target.processBusiness();
}
}
對于動態代理:
public class PermissionHandler implements InvocationHandler {
private Object target;
public LoggerHandler(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
checkPermission();
Object result = method.invoke(this.target,args);
return result;
}
}
測試代碼:
BusinessProcessImpl impl = new BusinessProcessImpl();
PermissionHandler handler = new PermissionHandler (impl);
BusinessProcess proxy = (BusinessProcess)Proxy.newProxyInstance(impl.getClass().getClassLoader(),impl.getClass().getInterfaces(), handler);
proxy.processBusiness();
注意:
proxy對象是BusinessProcess接口的一個實現類,但是不是BusinessProcessImpl的子類
看起來好像靜態代理和動態代理沒什么區別,但是仔細一看,靜態代理代理的target只能是BusinessProcess對象,而動態代理卻能夠代理任何一個Object對象,這就是關鍵區別。所以程序中不需要為每個核心類寫一個Proxy,而公用一個就可以。
動態代理的實現原理:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0,proxyClassFile.length);
這是java.lang.reflect.Proxy的兩行關鍵代碼,第一行代碼生成名為proxyName, 實現的接口為interfaces的一個類的字節碼。
第二行代碼,將生成的字節碼注入到classloader中去。
第一次為某個object生成proxyClass可能比較耗費性能,但是Proxy方法作了緩存,可以彌補這一點。此外,動態代理只能夠對interfaces進行動態的代理, 也就是說它先找出需要代理的對象實現的所有的interface, 然后只對所有的這些interface的所有的方法代理,對象除了interfaces以外的方法不予處理。