代理模式分爲兩種,一種是靜態代理模式,一種是動態代理模式。 靜態代理模式:在程序運行以前須要寫好代理類 動態代理模式:在程序運行期間動態生成代理類
動態代理實現的步驟: (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的全部接口 //第三個參數爲處理類
上面的內容是幾年前在網上看到的,具體出自那篇文章忘記了,動態代理的處理過程大致如上。java
經過看馬士兵的設計模式中的代理模式教程,對代理模式的內部實現原理有了更清楚的認識,下面的圖片是本身總結的代理類的產生過程: spring
下面的代碼來自馬士兵關於動態代理講解的源碼編程
//模擬代理類的實現代碼 //把出來的內容寫入文件中 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方法,經過上面的流程梳理,對於代理模式理解就更容易一些。ide
spring aop面向切面的編程也是使用動態代理模式來實現的。函數