一、反射
反射在之前的文章中詳細的解釋過了,簡單概括就是:可以動態的獲取到一個類內部的所有的資訊,動態的去創建物件和使用物件以及可以操作物件的屬性和方法,
二、代理
首先解釋一下代理:使用一個代理物件將物件包裝起來,然后用該代理物件來取代該物件,任何對原始物件的呼叫都要通過代理,代理物件決定是否以及何時呼叫原始物件的方法,
三、靜態代理
靜態代理:被代理物件和代理物件要實作同一套介面且代理物件內部要包含被代理物件,被代理物件覆寫重寫介面方法,在方法內部加上實際業務上的增強,
代碼目錄

代碼演示
//公共介面 public interface ZhangSanInterface { //定義一個吃飯的抽象方法 void eat(); } //張三類 public class ZhangSan implements ZhangSanInterface { @Override public void eat() { System.out.println("吃飯,,,"); //實作方法體 } } //張三代理類 public class ZhangSanProxy implements ZhangSanInterface{ private ZhangSanInterface zhangSanInterface; public ZhangSanProxy(ZhangSanInterface zhangSanInterface) { this.zhangSanInterface = zhangSanInterface; } @Override public void eat() { System.out.println("飯前洗手,,"); //方法前增強 zhangSanInterface.eat(); System.out.println("飯后洗碗,,"); //方法后增強 } } //測驗類 public class Main01 { public static void main(String[] args) { ZhangSanProxy proxy = new ZhangSanProxy(new ZhangSan()); //代理物件中傳入張三物件 proxy.eat(); } }

總結:靜態代理不需要使用反射機制就能夠實作,但是也存在了很明顯的缺陷,如果想要在加一些其他的被代理類,必須要修改代碼,不符合開閉原則(對外擴展開放,對內修改關閉),擴展性差、維護性差,
四、動態代理
動態代理:在程式的執行時(動態),使用jdk的反射機制,創建物件的能力,創建的是代理類的物件,而不用我們自己創建類檔案,
1、JDK動態代理
使用java反射包中的類和介面實作動態代理的功能, 反射包 java.lang.reflect,里面有三個類:InvocationHandler、Method、Proxy
1) InvocationHandler介面(呼叫處理器) :就-一個方法invoke ( )
invoke():表示代理物件要執行的功能代碼,你的代理類要完成的功能就寫在invoke ()方法中,
代理類完成的功能:
1.呼叫目標方法,執行目標方法的功能
2.功能增強,在目標方法呼叫時,增加功能,
方法原型:
引數: object proxy :jdk創建的代理物件,無需賦值,
Method method: 目標類中的方法,jdk提供me thod物件的
object[] args: 目 標類中方法的引數,jdk提供的 ,
public object invoke (object proxy, Method method, Object[] args)
InvocationHandler介面:表示你的代理要千什么,
怎么用: 1.創建類實作介面Invocati onHandler
2.重寫invoke()方法,把原來靜態代理中代理類要完成的功能,寫在這,
2) Method類:表示方法的,確切 的說就是目標類中的方法.
作用:邇過Method可以執行某個目標類的方法,Method. invoke() ;
method. invoke(目標物件,方法的引數)
3) Proxy類: 核心的物件,創建代理物件,之前創建物件都是new類的構造方法(),現在我們是使用Proxy類的方法,代替new的使用,
方法:靜態方法 newProxyInstance ()
作用是:創建代理物件, 等同于靜態代理中的 代理類 proxy = new 代理類() ;
引數:
1. ClassLoader loader 類加載器,負責向記憶體中加載物件的,使用反射獲取物件的ClassLoader類a,a. getCalss () .getClassLoader(),目標物件的類加載器,
2. Class<?>[] interfaces:介面,目標物件實作的介面,也是反射獲取的,
3. InvocationHandler h :我們自己寫的,代理類要完成的功能,
回傳值:newProxyInstance () 的回傳值就是代理物件,
實作動態代理的步驟
1.創建介面,定義目標類要完成的功能
2.創建目標類實作介面
3.創建InvocationHandler介面的實作類,在invoke方法中完成代理類的功能
1.呼叫目標方法
2.增強功能
4.使用Proxy類的靜態方法,創建代理物件,并把回傳值轉為介面型別,
代碼目錄

代碼展示
//目標介面 public interface Target { void eat(); } //目標類 public class TargetImpl implements Target { @Override public void eat() { System.out.println("吃飯飯,,"); } } //必須實作InvocationHandler介面,完成動態代理要做的功能(1.呼叫目標方法 2.功能增強) public class MyHandler implements InvocationHandler { private Object taget; public MyHandler(Object taget) { this.taget = taget; } //動態代理:物件是活動的,不是固定的,需要傳進來 //傳入是誰,就給誰創建代理, @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("洗手手,,"); Object invoke = method.invoke(taget, args);//執行目標方法 System.out.println("洗碗碗,,"); return null; } } //主函式 public class Main02 { public static void main(String[] args) { //1、創建目標物件 Target taget = new TargetImpl(); //2、創建InvocationHandler物件 InvocationHandler handler = new MyHandler(taget); //3、創建代理物件 Target proxy = (Target) Proxy.newProxyInstance( taget.getClass().getClassLoader(), taget.getClass().getInterfaces(), handler); //4、通過代理執行方法 proxy.eat(); } }

2、CGLIB動態代理
cglib是第三方的工具類,創建代理物件,cglib原理是繼承,通過繼承目標類,創建它的子類,在子類中重寫重寫父類中同名的方法,實作功能修改/增強,cglib動態代理要求目標類能夠被繼承,
目錄展示

代碼展示
//目標類 public class Target { public void eat(){ System.out.println("吃飯飯,,"); } } //實作MethodInterceptor介面 public class CglibProxy implements MethodInterceptor { private Object target; public CglibProxy(Object target) { this.target = target; } /** * @param proxy 代理物件參考 * @param method 被代理物件的方法的描述參考 * @param objects 方法的引數 * @param methodProxy 代理物件的 對目標物件的方法的描述 * @return * @throws Throwable */ @Override public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("洗手手,,"); method.invoke(target,objects); System.out.println("洗碗碗,,"); return null; } } /主方法測驗 public class Main03 { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(new Target()); Target target = (Target) Enhancer.create(Target.class, cglibProxy); target.eat(); } }
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/438611.html
標籤:Java
上一篇:SpringBoot進階教程(七十三)整合elasticsearch
下一篇:java中的列舉
