[102]技術-設計模式[代理模式]
代理模式
對於client -> server 訪問模式,如果我想在client 訪問 server時候多做一些工作,那麼可以是用程式碼,互動模式就變為client-> serverProxy -> server.
其具體的java 虛擬碼如下:
public interface iA
{
public void do();
}
public class RealA implement iA
{
public void do()
{
//dosomething....
}
}
public ProxyA implement iA //運用代理後客戶端訪問介面不變所以需要繼承相同的介面。
{
RealA a;
public void do()
{
//create A if a is not create
//dosomething before .....
a.do();
//dosomething after .....
}
}
main()
{
iA a = new ProxyA();
}
動態代理模式
現在我們知道了簡單的代理模式,如果A有多個實現類,比如RealA,RealA1,RealA2,難道我要對每個RealA? 類寫一個代理類嘛?且就算你寫了 ProxyRealA,ProxyRealB,我們也不太好統一呼叫。
代理有一個目的就是client -> proxy -> server這種模式中的server 封裝成一種統一呼叫,不用管其內部實現的複雜性。
那麼我們有沒有辦法在程式執行時候自動生成ProxyReal呢?
其大概虛擬碼如下:
InvocationHanderAimpl implements InvacationHandler
{
/**
* 這個方法實現就是類似ProxyA.do()方法類似的功能,在呼叫具體方法前後做一些處理。<br>
*/
public Object invoke(Object proxy, Method method, Object[] args)
{
... do something before invoke.
method.invoke(proxy,args);
.. do something after invoke.
}
}
main()
{
// getProxyInstance() 為iA a = new ProxyA();動態代理版本。
// InvocationHandler 代表了該代理類具體行為,即執行方法前後如何處理。
iA dynamicProxyObj = getProxyInstance(A.class,Aimpl.class,InvocationHandler);
dynamicProxyObj .do();
}
動態代理的兩種具體實現
- jdk 的版本
public class ProxyHandler implements InvocationHandler
{
private Object proxied;
public ProxyHandler( Object proxied )
{
this.proxied = proxied;
}
public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
{
//在轉調具體目標物件之前,可以執行一些功能處理
//轉調具體目標物件的方法
return method.invoke( proxied, args);
//在轉調具體目標物件之後,可以執行一些功能處理
}
}
main()
{
RealA realA= new RealA ();
iA proxiedA= (A)Proxy.newProxyInstance(A.class.getClassLoader(),
new Class[]{iA.class},
new ProxyHandler(realA));
iA.do();
}
這裡重點注意:
1.invocationHandler的實現。
2.newProxyInstance 的方法引數,interfaces只接收介面型別,即iA.class ,不接收RealA.class
//proxy.java
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h){
}
- cglib版實現
關於cglib,從網上找到英文版的介紹:
Cglib is an open source library that capable creating and loading class files in memory during Java run time. To do that it uses Java byte-code generation library ‘asm’, which is a very low level byte code creation tool,其開源類庫為:net.sf.cglib.proxy.*。
我們先看看原始碼如何建立Cglib代理類的
package com.thoughtworks.proxy.factory;
.......
import net.sf.cglib.core.CodeGenerationException;
import net.sf.cglib.core.DefaultNamingPolicy;
import net.sf.cglib.core.Predicate;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.InvocationHandler;
import net.sf.cglib.proxy.Proxy;
.......
public class CglibProxyFactory extends AbstractProxyFactory {
{
public <T> T createProxy(Invoker invoker, Class... types) {
Class type = this.getSingleClass(types); //type =null ,說明types物件全部是介面,沒有一個類
if(type == null) {
//全部是介面使用標準jdk的代理方式建立代理類,即proxy.newProxyInstance();
return standardProxyFactory.createProxy(invoker, types);
} else if(type.isPrimitive()) {
throw new IllegalArgumentException("Cannot subclass primitive type");
} else {
Class[] interfaces = this.getInterfaces(types);
Enhancer enhancer = new Enhancer();
while(true) {
enhancer.setSuperclass(type);
enhancer.setInterfaces(interfaces);
enhancer.setCallback(new CglibProxyFactory.CGLIBInvocationHandlerAdapter(invoker));
Object proxy;
try {
proxy = enhancer.create();
return proxy;
} catch (CodeGenerationException var8) {
Throwable wrapper = var8.getCause();
if(wrapper != null && wrapper.getCause() instanceof SecurityException && enhancer.getNamingPolicy() != this.namingPolicy) {
enhancer.setNamingPolicy(this.namingPolicy);
continue;
}
} catch (IllegalArgumentException var9) {
;
} catch (NoSuchMethodError var10) {
;
}
proxy = this.createWithConstructor(type, enhancer);
return proxy;
}
}
}
}
其具體如何建立和使用CglibProxy可以參考部落格:http://blog.csdn.net/ljphhj/article/details/20483171
兩種方式的優缺點:
CGLib建立的動態代理物件效能比JDK建立的動態代理物件的效能高不少,但是CGLib在建立代理物件時所花費的時間卻比JDK多得多,所以對於單例的物件,因為無需頻繁建立物件,用CGLib合適,反之,使用JDK方式要更為合適一些。同時,由於CGLib由於是採用動態建立子類的方法,對於final方法,無法進行代理!
說在後面的話
這篇文章只是簡單的介紹proxy幹了一件什麼事情。
從具體的技術層面還有以下疑問:
1.ClassLoader 裝載的是哪個類?如果是一個介面的話類是如何載入進來的。
2.Cglib與jdk Proxy類的區別。
這兩個問題以後待分析。
參考
關於cglib:
https://www.programcreek.com/java-api-examples/index.php?api=net.sf.cglib.proxy.MethodInterceptor
https://github.com/cglib/cglib/wiki/Tutorial
相關文章
- 設計模式-代理模式設計模式
- 設計模式----代理模式設計模式
- 設計模式~代理模式設計模式
- 【設計模式】代理模式設計模式
- 設計模式——代理模式設計模式
- js設計模式--代理模式JS設計模式
- Java設計模式—代理模式Java設計模式
- 設計模式之代理模式設計模式
- Java設計模式-代理模式Java設計模式
- 《設計模式》之代理模式設計模式
- PHP設計模式-代理模式PHP設計模式
- 設計模式 #5 (策略模式、代理模式)設計模式
- 代理設計模式設計模式
- Javascript設計模式之代理模式JavaScript設計模式
- Javascript設計模式(五)代理模式JavaScript設計模式
- JS設計模式四:代理模式JS設計模式
- Java 設計模式(四)《代理模式》Java設計模式
- Java設計模式之代理模式Java設計模式
- 設計模式學習——代理模式設計模式
- 設計模式 - 代理模式詳解設計模式
- 設計模式——代理模式的思考設計模式
- 軟體設計模式————(代理模式)設計模式
- 設計模式:代理模式詳解設計模式
- 極簡設計模式-代理模式設計模式
- 設計模式--介面卡模式/代理模式設計模式
- C++設計模式之Proxy模式(代理模式)C++設計模式
- 簡說設計模式——代理模式(續)設計模式
- 設計模式之代理模式(proxy pattern)設計模式
- 設計模式漫談之代理模式設計模式
- C++設計模式之代理模式C++設計模式
- Java設計模式之(五)——代理模式Java設計模式
- 搞懂設計模式——代理模式 + 原理分析設計模式
- 23種設計模式(四)-代理模式設計模式
- 23天設計模式之代理模式設計模式
- 設計模式之代理設計模式
- 23種設計模式之代理模式(靜態代理)設計模式
- 【設計模式】-代理模式及動態代理詳解設計模式
- 設計模式(七)Android中的代理模式設計模式Android
- 每天一個設計模式·代理模式設計模式