基於介面和子類的兩種動態代理的解析及使用
阿新 • • 發佈:2018-12-13
基於介面:
package com.itheima.proxy; 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(); /** * 動態代理: * 特點:位元組碼隨用隨建立,隨用隨載入 * 作用:不修改原始碼的基礎上對方法增強 * 分類: * 基於介面的動態代理 * 基於子類的動態代理 * 基於介面的動態代理: * 涉及的類:Proxy * 提供者:JDK官方 * 如何建立代理物件: * 使用Proxy類中的newProxyInstance方法 * 建立代理物件的要求: * 被代理類最少實現一個介面,如果沒有則不能使用 * newProxyInstance方法的引數: * ClassLoader:類載入器 * 它是用於載入代理物件位元組碼的。和被代理物件使用相同的類載入器。固定寫法。 * Class[]:位元組碼陣列 * 它是用於讓代理物件和被代理物件有相同方法。固定寫法。 * InvocationHandler:用於提供增強的程式碼 * 它是讓我們寫如何代理。我們一般都是些一個該介面的實現類,通常情況下都是匿名內部類,但不是必須的。 * 此介面的實現類都是誰用誰寫。 */ 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; //1.獲取方法執行的引數 Float money = (Float)args[0]; //2.判斷當前方法是不是銷售 if("saleProduct".equals(method.getName())) { returnValue = method.invoke(producer, money*0.8f); } return returnValue; } }); proxyProducer.saleProduct(10000f); } }
基於子類:
package com.itheima.cglib; 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 Client { public static void main(String[] args) { final Producer producer = new Producer(); /** * 動態代理: * 特點:位元組碼隨用隨建立,隨用隨載入 * 作用:不修改原始碼的基礎上對方法增強 * 分類: * 基於介面的動態代理 * 基於子類的動態代理 * 基於子類的動態代理: * 涉及的類:Enhancer * 提供者:第三方cglib庫 * 如何建立代理物件: * 使用Enhancer類中的create方法 * 建立代理物件的要求: * 被代理類不能是最終類 * create方法的引數: * Class:位元組碼 * 它是用於指定被代理物件的位元組碼。 * * Callback:用於提供增強的程式碼 * 它是讓我們寫如何代理。我們一般都是些一個該介面的實現類,通常情況下都是匿名內部類,但不是必須的。 * 此介面的實現類都是誰用誰寫。 * 我們一般寫的都是該介面的子介面實現類:MethodInterceptor */ 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); } }