動態代理常用的有兩種方式
阿新 • • 發佈:2020-07-13
一、JDK代理
public class Client { public static void main(String[] args) { final Product product = new Product(); /** * 動態代理: * 特點:位元組碼隨用隨建立,隨用隨載入 * 作用: 不修改原始碼的基礎上對方法進行增強 * * 分類: * 基於介面的動態代理(一個是實現) * 基於子類的動態代理(一個是繼承) * 基於介面的動態代理: * 涉及的類:proxy * 提供方:JDK官方 * 怎麼樣建立代理物件: * 使用proxy類中的newProxyInstance * * 建立代理物件的要求“ * 被代理類最少要實現一個介面,如果沒有則不能使用 * * newProxyInstance方法的引數: * ClassLoader:類載入器(被代理物件) * 作用:用於載入代理物件位元組碼的。和被代理物件使用相同的類載入器。固定寫法 * Class[]:位元組碼陣列 * 作用:用於讓代理物件和被代理物件有相同方法。固定寫法。 * InvocationHandler:用於提供增強的程式碼 * */ ProductInterface proxyProduct = (ProductInterface) Proxy.newProxyInstance(product.getClass().getClassLoader(), product.getClass().getInterfaces(), new InvocationHandler() { /** * 作用:執行被代理物件實現介面的所有方法都會經過invoke()方法 * * @param proxy 被代理物件 * @param method 當前執行的方法 * @param args 當前執行方法所需的引數 * @return 和被代理物件方法有相同的返回值 * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //提供增強的程式碼 Object returnValue = null; //1.獲取方法執行的引數 Float money = (Float) args[0]; if("saleProduct".equals( method.getName())){ returnValue = method.invoke(product, money * 0.8f); } return returnValue; } }); proxyProduct.saleProduct(1000); }
}
二、Cglib代理
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(1000f); } }