給動態代理舉個栗子:例如咱們平時買筆記本電腦,不少時候都是不從廠家拿貨,而是經過經銷商買電腦。代理模式出現解決了生產廠家的一些問題,那麼這個這個思想在咱們編程中是怎麼體現的啦???java
下面根據具體的案例來解釋編程
目錄結構ide
* 動態代理的特色就是字節碼,隨用隨建立,隨用隨加載 * 做用:在不修改源碼的基礎上對方法的加強 * 分類: * 基於接口動態代理 * 基於子類的動態代理 * 基於接口的動態代理 * 涉及類:proxy * 提供者:jdk官方 * 如何建立動態代理對象 * 使用proxy中的newProxyInstance方法 * 建立代理對象的要求: * 被代理的對象至少實現一個接口,若是沒有則不能使用 * newProxyInstance方法的參數 * classLoader 用於加載代理對象的字節碼,寫的是被代理對象的類加載器,和被代理對象使用相同的類加載器(固定寫法) * Class[] 它是用於代理對象和被代理對象有相同的方法(固定寫法) * InvocationHandler 用於加強的代理,含義是寫如何代理,咱們通常是寫一個該接口的實現類, * 一般狀況下是匿名內部類(匿名內部類訪問外部成員時,須要用final修飾),可是沒必要須,都是誰用誰寫
案例以下:測試
接口 package com.cc.proxy; public interface IProducer { public void saleProduct(float money); public void afterService(float money); }
package com.cc.proxy; /** * 一個生產者 */ public class Producer implements IProducer{ /** * 銷售 */ public void saleProduct(float money){ System.out.println("銷售產品,拿到錢:"+money); } /** * 售後 */ public void afterService(float money){ System.out.println("提供售後服務,並拿到錢"+money); } }
測試方法spa
package com.cc.proxy; import org.junit.Test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 模擬一個消費者 * 基於接口的動態代理,若是類不實現接口代理是沒法使用 */ public class Client { @Test public void test(){ final Producer producer=new Producer(); IProducer proxyProducer=(IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() { /** * 做用:執行被代理對象的任何接口的方法都會通過該方法 * @param proxy 代理對象的引用 * @param method 當前執行的方法 * @param args 當前執行該方法所須要的參數 * @return 和被代理對象方法具備相同的返回值 * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //加強的代碼 Object returnValue=null; //一、獲取方法執行的參數 Float money= (Float) args[0]; //2.判斷當前方法是否是銷售 if("saleProduct".equals(method.getName())){ returnValue=method.invoke(producer,money*0.8f); } return returnValue; } }); proxyProducer.saleProduct(12000f); } }
/** * 動態代理: * 特色:字節碼隨用隨建立,隨用隨加載 * 做用:不修改源碼的基礎上對方法加強 * 分類: * 基於接口的動態代理 * 基於子類的動態代理 * 基於子類的動態代理: * 涉及的類:Enhancer * 提供者:第三方cglib庫 * 如何建立代理對象: * 使用Enhancer類中的create方法 * 建立代理對象的要求: * 被代理類不能是最終類 * create方法的參數: * Class:字節碼 * 它是用於指定被代理對象的字節碼。 * * Callback:用於提供加強的代碼 * 它是讓咱們寫如何代理。咱們通常都是些一個該接口的實現類,一般狀況下都是匿名內部類,但不是必須的。 * 此接口的實現類都是誰用誰寫。 * 咱們通常寫的都是該接口的子接口實現類:MethodInterceptor */
package com.cc.cglib; /** * 一個生產者 */ public class Producer { /** * 銷售 */ public void saleProduct(float money){ System.out.println("銷售產品,拿到錢:"+money); } /** * 售後 */ public void afterService(float money){ System.out.println("提供售後服務,並拿到錢"+money); } }
package com.cc.cglib; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.junit.Test; import java.lang.reflect.Method; /** * 模擬一個消費者 */ public class Client { @Test public void test(){ final Producer producer = new Producer(); Producer cglibProducer = (Producer)Enhancer.create(producer.getClass(), new MethodInterceptor() { /** * 執行北地阿里對象的任何方法都會通過該方法 * @param proxy * @param method * @param args * 以上三個參數和基於接口的動態代理中invoke方法的參數是同樣的 * @param methodProxy :當前執行方法的代理對象 * @return * @throws Throwable */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //提供加強的代碼 Object returnValue=null; //1.獲取方法執行的參數 Float money=(float)args[0]; //2.判斷當前方法是否是銷售 if("saleProduct".equals(method.getName())){ returnValue=method.invoke(producer,money*0.8f); } return returnValue; } }); cglibProducer.saleProduct(12000f); } }
測試結果以下:代理