亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java動態代理常用方式有哪些

發布時間:2021-11-22 17:08:13 來源:億速云 閱讀:149 作者:iii 欄目:開發技術

本篇內容介紹了“Java動態代理常用方式有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

    什么是動態代理?

    動態代理就是,在程序運行期,創建目標對象的代理對象,并對目標對象中的方法進行功能性增強的一種技術。在生成代理對象的過程中,目標對象不變,代理對象中的方法是目標對象方法的增強方法。可以理解為運行期間,對象中方法的動態攔截,在攔截方法的前后執行功能操作(也可以對原方法的參數進行操作)。

    代理類在程序運行期間,創建的代理對象稱之為動態代理對象。這種情況下,創建的代理對象,并不是事先在Java代碼中定義好的。而是在運行期間,根據我們在動態代理對象中的“指示”,動態生成的。也就是說,你想獲取哪個對象的代理,動態代理就會為你動態的生成這個對象的代理對象。動態代理可以對被代理對象的方法進行功能增強。有了動態代理的技術,那么就可以在不修改方法源碼的情況下,增強被代理對象的方法的功能,在方法執行前后做任何你想做的事情。

    特點:字節碼隨用隨創建,隨用隨加載

    作用:不修改源碼的基礎上對方法增強

    動態代理的常用兩種方式:

    1.基于接口的動態代理

    提供者:JDK

    使用JDK官方的Proxy類創建代理對象

    注意:代理的目標對象必須實現接口(至少一個)

    2.基于類的動態代理

    提供者:第三方 CGLib

    使用CGLib的Enhancer類創建代理對象

    注意:被代理類不能用 final 修飾的類(最終類)。如果報 asmxxxx 異常,需要導入 asm.jar包

    //JDK動態代理(基于接口的動態代理)
    Proxy.newProxyInstance(三個參數);
    	ClassLoader:類加載器
    		它是用于加載代理對象字節碼的。和被代理對象使用相同的類加載器。(固定寫法)
    	Class[]:字節碼數組
    		它是用于讓代理對象和被代理對象有相同方法。(固定寫法)
    	InvocationHandler:用于提供增強的代碼
    		它是讓我們寫如何代理。我們一般都是寫一個該接口的實現類,通常情況下都是匿名內部類,但不是必須
    		InvocationHandler該接口的實現類是誰用誰寫,此時我們用就需要我們自己寫

    此處以一個演員的例子為例:

    在很久以前,演員和劇組都是直接見面聯系的。沒有中間人環節。

    而隨著時間的推移,產生了一個新興職業:經紀人(中間人),這個時候劇組再想找演員就需要通過經紀人來找了。下面我們就用代碼演示出來。

    package com.haust.service;
    public interface IActor {
    	/**
    	* 基本演出
    	* @param money
    	*/
    	public void basicAct(float money);
    	/**
    	* 危險演出
    	* @param money
    	*/
    	public void dangerAct(float money);
    }
    package com.haust.serviceImpl;
    import com.haust.service.IActor;
    public class Actor implements IActor {
    	/**
    	* 一個演員
    	*/
    	//實現了接口,就表示具有接口中的方法實現。即:符合經紀公司的要求
    	@Override
    	public void basicAct(float money) {
    		System.out.println("拿到錢,開始基本的表演:"+money);
    	}
    	@Override
    	public void dangerAct(float money) {
    		System.out.println("拿到錢,開始危險的表演:"+money);
    	}
    }
    package com.haust.test;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import com.haust.service.IActor;
    import com.haust.serviceImpl.Actor;
    public class Client {
    	public static void main(String[] args) {
    		//一個劇組找演員:
    		final Actor actor = new Actor();//被代理的類
    		/**
    		* 代理:
    		* 間接。
    		* 獲取代理對象:
    		* 要求:
    		* 被代理類最少實現一個接口
    		* 創建的方式
    		* Proxy.newProxyInstance(三個參數)
    		* 參數含義:
    		* ClassLoader:和被代理對象使用相同的類加載器。
    		* Interfaces:和被代理對象具有相同的行為。實現相同的接口。
    		* InvocationHandler:如何代理。
    		* 
    		*/
    		//(IActor)Proxy.newProxyInstance,這里強制轉換必須是接口類型
    		IActor proxyActor = (IActor)Proxy.newProxyInstance(actor.getClass().getClassLoader(),
    				 actor.getClass().getInterfaces(),
    				 new InvocationHandler() {
    			 /**
    			 * 執行被代理對象的任何方法,都會經過該方法。
    			 * 此方法有攔截的功能。
    			 * 
    			 * 參數:
    			 * proxy:代理對象的引用。不一定每次都用得到
    			 * method:當前執行的方法對象
    			 * args:執行方法所需的參數
    			 * 返回值:
    			 * 當前執行被代理對象方法的返回值
    			 */
    					@Override
    					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    						String name = method.getName();
    						Float money = (Float) args[0];//執行的方法只有一個參數
    						Object rtValue = null;
    						//每個經紀公司對不同演出收費不一樣,此處開始判斷
    						if("basicAct".equals(name)){
    						//基本演出,沒有 2000 不演
    						if(money > 2000){
    						//看上去劇組是給了 8000,實際到演員手里只有 4000
    						//這就是我們沒有修改原來 basicAct 方法源碼,對方法進行了增強
    						rtValue = method.invoke(actor, money/2);
    						} }
    						if("dangerAct".equals(name)){
    						//危險演出,沒有 5000 不演
    						if(money > 5000){
    						//看上去劇組是給了 50000,實際到演員手里只有 25000
    						//這就是我們沒有修改原來 dangerAct 方法源碼,對方法進行了增強
    						rtValue = method.invoke(actor, money/2);
    						} }
    						return rtValue;
    					}
    				});
    		//沒有經紀公司的時候,直接找演員。
    		// actor.basicAct(1000f);
    		// actor.dangerAct(5000f);
    		//劇組無法直接聯系演員,而是由經紀公司找的演員
    		proxyActor.basicAct(2000f);//價格低于2000不演
    		proxyActor.dangerAct(50000f);
    		
    	}
    }

    總結:

    首先需要創建一個interface然后一個class實現這個interface,然后對這個class進行代理,這個class必須實現至少一個接口

    基于子類的動態代理

    設計的類:Enhancer
    提供者:第三方cglib庫
    如何創建代理對象:
    	使用Enhancer類中的create方法
    創建代理對象的要求:
    	被代理對象不是最終類(最終類沒有子類)
    create方法的參數:
    	Class方法的參數:
    		Class:字節碼
    			它是用于指定被代理對象的字節碼
    		callback:用于提供增強的代碼
    			它是讓我們寫如何代理。我們一般都是些一個該接口的實現類,通常情況下都是匿名內部類,但不是必須的。此接口的實現類都是誰用誰寫。
    			我們一般寫的都是該接口的子接口實現類:MethodInterceptor
    //CGLib動態代理(基于子類的動態代理)
    Enhancer.create(兩個參數);

    代碼如下:

    package com.haust.serviceImpl;
    
    public class Actor{//沒有實現任何接口
    	/**
    	* 一個演員
    	*/
    	public void basicAct(float money) {
    		System.out.println("拿到錢,開始基本的表演:"+money);
    	}
    	public void dangerAct(float money) {
    		System.out.println("拿到錢,開始危險的表演:"+money);
    	}
    }
    package com.haust.test;
    import java.lang.reflect.Method;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    import com.haust.serviceImpl.Actor;
    public class test {
    	public static void main(String[] args) {
    		 Actor actor = new Actor();//需要創建此被代理的對象
    		 /**
    		 * 基于子類的動態代理
    		 * 要求:
    		 * 被代理對象不能是最終類
    		 * 用到的類:
    		 * Enhancer
    		 * 用到的方法:
    		 * create(Class, Callback)
    		 * 方法的參數:
    		 * Class:被代理對象的字節碼
    		 * Callback:如何代理
    		 * @param args
    		 */
    		 //此時強轉的類的類型就是被代理類的類型
    		 Actor cglibActor = (Actor)Enhancer.create(actor.getClass(),new MethodInterceptor() {
    			@Override
    			public Object intercept(Object proxy, Method method, Object[] args, MethodProxy  methodProxy) throws Throwable {
    				/**
    				* 執行被代理對象的任何方法,都會經過該方法。在此方法內部就可以對被代理對象的任何
    				方法進行增強。
    				* 
    				* 參數:
    				* 前三個和基于接口的動態代理是一樣的。
    				* MethodProxy:當前執行方法的代理對象。
    				* 返回值:
    				* 當前執行方法的返回值
    				*/
    				String name = method.getName();
    				Float money = (Float) args[0];
    				Object rtValue = null;
    				if("basicAct".equals(name)){
    				//基本演出
    				if(money > 2000){
    				rtValue = method.invoke(actor, money/2);
    				} }
    				if("dangerAct".equals(name)){
    					//危險演出
    					if(money > 5000){
    					rtValue = method.invoke(actor, money/2);
    					} 
    				}
    				return rtValue;
    			}
    		});
    		 cglibActor.basicAct(10000);
    		 cglibActor.dangerAct(100000);
    	}
    }

    “Java動態代理常用方式有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    扎鲁特旗| 张家口市| 小金县| 团风县| 于都县| 南召县| 邳州市| 应用必备| 博白县| 永仁县| 新化县| 兴和县| 积石山| 彩票| 吉安市| 汉阴县| 阳朔县| 广宗县| 慈溪市| 宽城| 阿鲁科尔沁旗| 白沙| 彰武县| 高州市| 临汾市| 新闻| 张家川| 连平县| 亳州市| 即墨市| 钦州市| 武乡县| 滦南县| 子长县| 蓬溪县| 松溪县| 枣强县| 广宗县| 嘉峪关市| 屯留县| 临漳县|