中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

Java中動態代理的示例分析

發布時間:2021-08-07 14:44:41 來源:億速云 閱讀:151 作者:小新 欄目:編程語言

小編給大家分享一下Java中動態代理的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

基礎:需要具備面向對象設計思想,多態的思想,反射的思想;

Java動態代理機制的出現,使得Java開發人員不用手工編寫代理類,只要簡單地指定一組接口及委托類對象,便能動態地獲得代理類。代理類會負責將所有的方法調用分派到委托對象上反射執行,在分派執行的過程中,開發人員還可以按需調整委托類對象及其功能,這是一套非常靈活有彈性的代理框架。通過閱讀本文,讀者將會對Java動態代理機制有更加深入的理解。本文首先從Java動態代理的運行機制和特點出發,對其代碼進行了分析,推演了動態生成類的內部實現。

代理模式的基本概念和分類

代理模式:為其他對象提供一個代理,來控制對這個對象的訪問。代理對象起到中介作用,可以去掉服務或者增加額外的服務,或者引用別人的話:“代理類負責為委托類預處理消息,過濾消息并轉發消息,以及進行消息被委托類執行后的后續處理。”

代理模式在開發中的應用場景

遠程代理:為不同地理的對象提供局域網代表對象。

虛擬代理:根據需要將資源消耗很大的對象進行延遲,真正需要的時候進行創建。比如網頁中的先顯示文字再顯示圖片。

保護代理:控制不同用戶的訪問權限。比如:只有當客戶注冊成功之后,才可以進行增刪改查等操作。

智能引用代理:提供對目標代理額外的服務。

代理模式的實現方式

使用繼承和聚合實現動態代理,哪種更好呢!

public interface Moveable {
	public void move();
}
public class Car implements Moveable{
	@Override 
	  public void move() {
		try {
			Thread.sleep(new Random().nextint(1000));
			System.out.println("……行駛中……");
		}
		catch(InterruptedException e) {
			// TODO Auto-generated catch block 
			e.printStackTrace();
		}
	}
}
public class Car2 extends Car{
	@Override 
	  public void move() 
	  {
		//分離代碼,增加業務邏輯 
		long startTime=System.currentTimeMillis();
		System.out.println("汽車開始行駛……");
		super.move();
		long endTime=System.currentTimeMillis();
		System.out.println("汽車結束行駛……時間:"+(endTime-startTime)+"ms");
	}
}

繼承方式實現代理

Moveablecar2=newCar2();
car2.move();

聚合方式實現代理

Carcar=newCar();
Moveablem=newCar3(car);
m.move();

總結

使用繼承方式不夠靈活,當功能疊加的時候,只能臃腫的擴展代理類;
使用聚合的方式,代理之間可以相互傳遞,靈活的組合代理;

public class CarLogProxy extends Car{
	@Override 
	  public void move() 
	  {
		//分離代碼,增加業務邏輯 
		long startTime=System.currentTimeMillis();
		System.out.println("日志開始……");
		super.move();
		long endTime=System.currentTimeMillis();
		System.out.println("日志結束……");
	}
}
public class CarTimeProxy implements Moveable {
	public CarTimeProxy(Car car) 
	  {
		super();
		this.car=car;
	}
	private Carcar;
	@Override 
	  public void move() {
		//分離代碼,增加業務邏輯 
		long startTime=System.currentTimeMillis();
		System.out.println("汽車開始行駛……");
		car.move();
		long endTime=System.currentTimeMillis();
		System.out.println("汽車結束行駛……時間:"+(endTime-startTime)+"ms");
	}
}
@Test: 
Car car =new Car();
CarTimeProxy ctp=new CarTimeProxy(car);
CarLogProxy clp=new CarLogProxy(ctp);
clp.move();
//還可以通過接口相互傳遞代理實例 
CarLogProxy clp1=new CarLogProxy(car);
CarTimeProxy ctp1=new CarTimeProxy(clp1);
ctp1.move();

JDK動態代理和CGlib動態代理

JDK動態代理

代理實現

如果不同的對象要實現相同功能的代理類,應該如何處置?

此時可以試著將其集成在同一個代理類中-----動態代理:實現對不同類/不同方法的代理;

大致過程如下:

Java中動態代理的示例分析

Java動態代理類位于java.lang.reflect包下,一般主要涉及到一下兩個類:

(1)InterfaceInvocationHandler:該接口中僅定義了一個方法Publicobjectinvoke(Objectobj,Methodmethod,Object[]args)

obj:一般是指代理類

method:是被代理的方法

args為該方法的參數數組。

這個抽象的方法在代理類中動態實現。

(2)Proxy:該類即為動態代理類

statixObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)

返回甙類類的一個實例,返回后的代理類可以當做被代理類使用(可以使用被代理類在接口中聲明過的方法);

實現實例:

@ TimeHandler 
public class TimeHandler   implements InvocationHandler {
	public TimeHandler(Object target) {
		super();
		this.target = target;
	}
	private Objecttarget;
	/* 
  * 參數: 
  * proxy 被代理對象 
  * method 被代理對象的方法 
  * args 方法的參數 
  * 
  * 返回值: 
  * Object 方法返回值 
  */
	@Override 
	  public Object invoke(Object proxy, Method method,Object[] args) 
	    throws Throwable {
		long startTime=System.currentTimeMillis();
		System.out.println("汽車開始行駛……");
		method.invoke(target);
		long endTime=System.currentTimeMillis();
		System.out.println("汽車結束行駛……時間:"+(endTime-startTime)+"ms");
		return null;
	}
}
@被代理類的接口
public interface Moveable {
  public void move();
}
@被代理的類
public class Car implements Moveable{
	@Override 
	  public void move() {
		try {
			Thread.sleep(new Random().nextint(1000));
			System.out.println("……行駛中……");
		}
		catch (InterruptedException e) {
			// TODO Auto-generated catch block 
			e.printStackTrace();
		}
	}
}

@測試

public class Test { 
  /** 
  * JDk動態代理的測試類 
  */ 
  public static void main(String[] args) { 
   Car car=new Car(); 
   InvocationHandler h=new TimeHandler(car); 
   Class<?>cls=car.getClass(); 
   /* 
    * loader 類加載器 
    * interfaces 實現接口 
    * h InvocationHandler 
    */ 
   Moveable m=(Moveable)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),h); 
   m.move(); 
  } 
}

&&測試結果

Java中動態代理的示例分析

梳理總結

所為的DynamicProxy是這樣一種class:

它是在運行時生成的class,該class需要實現一組interface,使用動態代理類的時候,必須實現InvocationHandler接口。

JDK動態代理的一般步驟

1.創建一個實現接口InvocationHandler的類,它必須實現invoke()

2.創建被代理的類以及接口

3.調用Proxy的靜態方法,創建一個代理類

newProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)

4.通過代理調用方法

Java中動態代理的示例分析

CGlib動態代理的實現

代理實現

@引入cglib-node-2.2.jar包

@CglibProxy攔截類實現接口MethodInterceptor:重寫intercept攔截方法

public class CglibProxy implements MethodInterceptor {
	private Enhancerenhancer=new Enhancer();
	public Object getProxy(Class cl) 
	  {
		//設置創建子類的類 
		enhancer.setSuperclass(cl);
		enhancer.setCallback(this);
		return enhancer.create();
	}
	/* 
  * 攔截所有目標類方法的調用 
  * object 目標類的實例 
  * m 目標方法的反射對象 
  * args 方法的參數 
  * proxy 代理類的實例 
  * 
  */
	@Override 
	  public Object intercept(Object obj, Method m,Object[] args,  MethodProxy proxy)throws Throwable 
	{
		System.out.println("日志開始……");
		//代理類調用父類的方法 
		proxy.invokeSuper(obj, args);
		System.out.println("日志結束……");
		return null;
	}
}

@被代理類Train

public class Train { 
  public void move() 
  { 
   System.out.println("火車行駛中……"); 
  } 
}

@測試類

public class Test { 
  /** 
  * cglibProxy動態代理測試類 
  */ 
  public static void main(String[] args) { 
   CglibProxy proxy=new CglibProxy(); 
   Train t=(Train)proxy.getProxy(Train.class); 
   t.move(); 
  } 
}

##測試結果:

Java中動態代理的示例分析

梳理總結

使用CglibProxy實現動態代理的一般步驟

1、創建類實現接口MethodInterceptor,并重寫intercept方法

2、創建被代理類

3、調用代理類自定義的方法,得到一個代理實例

4、通過代理實例調用被代理類的需要執行的方法

比較總結

JDK動態代理

1、只能代理實現了接口的類

2、沒有實現接口的類不能實現JDK的動態代理

CGlib動態代理

1、針對類來實現代理

2、對執行目標類產生一個子類,通過方法攔截技術攔截所有父類方法的調用。

模擬代理產生步驟

思路:

實現功能:通過Proxy的newProxyInstance返回代理對象

1、聲明一段源碼(動態產生代理)

2、編譯源碼(JDKCompilerAPI)產生新的類(代理類)

3、將這個類load到內存當中,產生一個新的對象(代理對象)

4、返回代理對象

完善動態代理實現

首先得到系統編譯器,通過編譯器得到文件管理者,然后獲取文件,然后編譯器執行編譯任務,完成編譯之后,將class文件加載到類加載器中,通過構造方法得到實例,然后調用newInstance()接收一個對象的實例。

(1)拿到編譯器JavaCompilercompiler=ToolProvider.getSystemJavaCompiler();

(2)文件管理者StandardJavaFileManagerfileMgr=Compiler.getStandardFileManager(null,null,null);

(3)獲取文件Iterableunits=fileMgr.getJavaFileObjects(filename);

(4)編譯任務CompilationTaskt=compiler.getTask(null,fileMgr,null,null,null,units);

(5)load到內存

ClassLoadercl=ClassLoader.getSystemClassLoader();

Classc=cl.loadClass(”com.imooc.proxy.$Proxy0”);

(6)通過代理對象的構造器構造實例

Constructorctr=c.getConstructor(infce);

ctr.newInstance(newCar());

-------

上說所說,內部的業務邏輯是硬編碼的,如何實現真正的動態代理,動態的指定業務邏輯呢?

1、需要創建一個事務處理器,首先創建一個接口也就是InvocationHandler,為了模擬JDK,這里把接口的名字和JDK事務處理器名稱一樣,同樣寫一個方法叫做invoke(),用來表示對某個對象的某個方法進行業務處理,所以需要把某個對象以及對象的方法作為invoke()方法的參數傳遞進來,invoke(Objectobj,Methodmethod),方法作為參數使用到了java反射,需要把此包引入。這樣InvocationHandler接口就完成了。

2、創建事務處理實現類比如說時間代理TimerProxy,實現了InvocationHandler接口,這樣結構就成了

——————TimerProxyimplementsInvocationHandler{ 
————————-@override 
————————-voidinvoke(Objectobj,Methodmethod){ 
———————————//業務邏輯<br> 
—————————————method.invoke(目標對象,參數); 
————————————//業務邏輯<br> 
——————————} 
—————————}

需要將目標對象傳入,沒有參數可以不寫參數,創建代理對象的構造方法,初始化目標對象

3、在Proxy類的newProxyInstance()方法中,除了要把目標Class接口作為參數外,還需要把事務處理器InvocationHandler傳進去,然后更改創建實例對象中硬編碼的部分用事務處理器方法替代即可。難點在于字符串的拼接。

以上是“Java中動態代理的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

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

AI

安仁县| 江永县| 遂平县| 大名县| 鄂尔多斯市| 岑巩县| 瑞丽市| 濮阳县| 彩票| 昂仁县| 夏邑县| 沧州市| 遵义县| 常山县| 博爱县| 德阳市| 张北县| 汾西县| 清流县| 临洮县| 司法| 新晃| 伊宁市| 宣威市| 自贡市| 长岛县| 准格尔旗| 延庆县| 吴桥县| 会昌县| 康平县| 务川| 上思县| 扎鲁特旗| 宽城| 东兰县| 肃宁县| 淮南市| 呼图壁县| 增城市| 云南省|