1.模式定義
代理模式是指其他對象使用代理來控制對對象的訪問。
2.代理分類
靜態代理分爲普通代理和強制代理兩種。通用模式是Subject接口,以及實現這個接口的兩個類:RealSubject類,Proxy代理類(傳入RealSubjct的實例)
普通代理,是指用戶無需知道RealSubject,只要知道代理並調用即可。這時需要將通用模式稍微修改。RealSubject的構造函數參數加入Subject類型的代理。Proxy類中直接new RealSubjct(this) 這時在客戶端直接new Proxy類,即可調用RealSubject的方法。
強制代理,是指用戶直接調用RealSubject,但是返回的是Proxy的實例。在通用模式的基礎上,Subject接口添加一個getProxy()方法的接口,RealSubject實現Subject的getProxy的方法,加入Proxy的對象,如果爲空,直接new Proxy(),然後對於RealSubject判斷有沒有代理,沒有代理的話拋出異常。這樣客戶端直接new RealSubject().getProxy()即可返回代理,並通過該代理,調用RealSubject中的方法。
動態代理:動態代理應用於AOP中。有兩種實現方式,一種是JDK實現的,針對實現接口的類。一種是CGLIB實現的,是對類的子類實現代理,所以不能對final的類實現動態代理。
JDK動態代理:
1.需要實現InvocationHandler接口的類,該類需要傳入Subject,重寫invoke方法,即實現對RealSubject的動態調用。
2.需要動態返回代理。Proxy.getNewProxy(classLoder,interfaces,handler) 返回的代理即可調用RealSubject中的方法。如果需要在切入點進行對象的功能增強,可在此方法之前進行攔截和過濾。
3.JDK動態代理實例
package com.sogou.proxy_test;
public interface IAdvice {
public void exec();
}
package com.sogou.proxy_test;
public class BeforeAdvice implements IAdvice{
public void exec() {
// TODO Auto-generated method stub
System.out.println("這是前置通知並且被執行");
}
}
package com.sogou.proxy_test;
public interface Subject {
public void dosomething(String str);
}
package com.sogou.proxy_test;
public class RealSubject implements Subject{
public void dosomething(String str) {
// TODO Auto-generated method stub
System.out.println("do something ---- >> "+str);
}
}
package com.sogou.proxy_test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
Object object=null;
public MyInvocationHandler(Object o){
object=o;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return method.invoke(this.object, args);
}
}
package com.sogou.proxy_test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class DynamicProxy <T>{
public static <T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){
if (true) {
(new BeforeAdvice()).exec();
}
return (T) Proxy.newProxyInstance(loader, interfaces, h);
}
}
package com.sogou.proxy_test;
public class Client {
public static void main(String[] args){
Subject subject=new RealSubject();
MyInvocationHandler h=new MyInvocationHandler(subject);
Subject proxy=DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), h);
proxy.dosomething("yeah");
}
}