動態代理模式實現原理
阿新 • • 發佈:2018-12-19
1.代理模式概念
代理模式分為兩種,一種是靜態代理模式,一種是動態代理模式。
靜態代理模式:在程式執行之前需要寫好代理類
動態代理模式:在程式執行期間動態生成代理類
2.動態代理的實現
動態代理實現的步驟:
(1)寫一個代理類SubjectHandler實現InvocationHandler介面,重寫invoke方法,
通過建構函式把代理的物件realSubject傳入到此處理類中,
在invoke方法中增加method.invoke(realSubject, args);
public interface Subject
{
public void rent();
}
public class RealSubject implements Subject
{
@Override
public void rent()
{
System.out.println("I want to rent my house");
}
}
public class SubjectHandler implements InvocationHandler
{
private Subject subject;
public SubjectHandler(Subject subject)
{
this .subject = subject;
}
@Override
public Object invoke(Object object, Method method, Object[] args) throws Throwable
{
System.out.println("before rent house");
method.invoke(subject, args);
System.out.println("after rent house");
return null;
}
}
(2)在呼叫方法中增加程式碼即可完成呼叫
public class Client
{
public static void main(String[] args)
{
RealSubject realSubject = new RealSubject();
//生成代理類的物件
Subject subject = (Subject)Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new SubjectHandler(realSubject));
subject.rent(); //呼叫代理類的方法
}
}
//第一個引數為realSubject的classloader
//第二個引數為realSubject的所有介面
//第三個引數為處理類
上面的內容是幾年前在網上看到的,具體出自那篇文章忘記了,動態代理的處理過程大體如上。
3.動態代理的實現過程
通過看馬士兵的設計模式中的代理模式教程,對代理模式的內部實現原理有了更清楚的認識,下面的圖片是自己總結的代理類的產生過程:
下面的程式碼來自馬士兵關於動態代理講解的原始碼
//模擬代理類的實現程式碼
//把出來的內容寫入檔案中
String fileName =
"d:/src/com/proxy/$Proxy1.java";
File f = new File(fileName);
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
//編譯檔案,
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(fileName);
CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
fileMgr.close();
//把class檔案載入到記憶體中,通過構造方法生成代理的物件
URL[] urls = new URL[] {new URL("file:/" + "d:/src/")};
URLClassLoader ul = new URLClassLoader(urls);
Class c = ul.loadClass("com.proxy.$Proxy1");
System.out.println(c);
Constructor ctr = c.getConstructor(InvocationHandler.class);
Object m = ctr.newInstance(h);
return m;
在生成的代理類中對應的方法如下
private static Method m0;
public final void rent() {
try {
super.h.invoke(this, m0, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
從上面我們可以看出,生成的代理物件subject 呼叫rent方法,其實是呼叫的上面代理類中生成的rent方法,在rent方法中呼叫了SubjectHandler 的invoke方法,通過上面的流程梳理,對於代理模式理解就更容易一些。
spring aop面向切面的程式設計也是使用動態代理模式來實現的。