動態代理:在不修改源碼的基礎上,對原有方法的加強。java
準備接口:測試
Iproducer.interface:spa
public interface Iproducer { public double saleProducer(double money); }
接口動態代理代理
producer.javacode
public class producer implements Iproducer{ public double saleProducer(double money) { System.out.println("賣出"+money); return money; } }
測試:對象
client.javapackage proxy;blog
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 基於接口的動態代理 */ public class client { public static void main(String[] args) { final producer producer=new producer(); Iproducer p =(Iproducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object value = null;
//只有一個參數 Double money = (Double) args[0]; if ("saleProducer".equals(method.getName())) { money = 0.8 * money; value = method.invoke(producer, money); } return value; } }); p.saleProducer(10000); } }
分析:經過getClass()、getClassLoad()加載字節碼文件,再加載接口字節碼文件(返回類型是接口類型)。在匿名內部類定義invoke方法接口
該方法在代理對象調用被代理對象方法時都會執行,傳入的參數也會傳入該方法,而後進行自定義的加強。返回值與被代理對象的方法的返回值一致。get
子類 動態代理源碼
producer.java
public class producer { public double saleProducer(double money) { System.out.println("賣出"+money); return money; } }
client.java
package proxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * 基於子類的動態代理 */ public class client2 { public static void main(String[] args) { final producer2 producer2=new producer2(); producer2 p = (producer2) Enhancer.create(producer2.getClass(), new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object value = null; Double money = (Double) args[0]; if ("saleProducer".equals(method.getName())) { money = 0.8 * money; value = method.invoke(producer2, money); } return value; } }); p.saleProducer(10000); } }
分析與上基本一致,要使用cglib.jar包