最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 動(dòng)態(tài)代理的多種實(shí)現(xiàn)方式

 更新時(shí)間:2021年06月07日 09:25:13   作者:卡修斯  
動(dòng)態(tài)代理實(shí)際上是JVM在運(yùn)行期動(dòng)態(tài)創(chuàng)建class字節(jié)碼并加載的過(guò)程。本文講述了Java 動(dòng)態(tài)代理的多種實(shí)現(xiàn)方式,感興趣的朋友可以選擇適合自己的方式

一、動(dòng)態(tài)代理簡(jiǎn)介

優(yōu)勢(shì):在不修改源碼的情況下,對(duì)目標(biāo)方法進(jìn)行相應(yīng)的增強(qiáng)。

作用:完成程序功能之間的松耦合。

二、動(dòng)態(tài)代理的多種實(shí)現(xiàn)

  • JDK代理:基于接口的動(dòng)態(tài)代理技術(shù)(缺點(diǎn),目標(biāo)對(duì)象必須有接口,如果沒(méi)有接口,則無(wú)法完成動(dòng)態(tài)代理的實(shí)現(xiàn))
  • cglib代理:基于父類(lèi)的動(dòng)態(tài)代理技術(shù)

兩者的區(qū)別如圖所示:

1. 基于JDK的實(shí)現(xiàn)

目標(biāo)接口類(lèi):

public interface TargetInterface {
	public void save();
	
	public void print(String str);
}

目標(biāo)類(lèi):

public class Target implements TargetInterface{
	
	public void save() {
		System.out.println("save running...");
	}
	
	public void print(String str) {
		System.out.println(str);
	}

}

增強(qiáng)類(lèi):

public class Advice {
	public void before() {
		System.out.println("前置增強(qiáng)");
	}

	public void after() {
		System.out.println("后置增強(qiáng)");
	}
}

測(cè)試類(lèi):

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {

	public static void main(String[] args) {
		
		//目標(biāo)對(duì)象
		final Target target = new Target();
		
		//增強(qiáng)對(duì)象
		final Advice advice = new Advice();
		
		TargetInterface proxyInstance = (TargetInterface)Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 					//目標(biāo)對(duì)象類(lèi)加載器
				target.getClass().getInterfaces(), 						//目標(biāo)對(duì)象相同的接口字節(jié)碼對(duì)象數(shù)組
				new InvocationHandler() {
					//調(diào)用代理對(duì)象的任何方法,實(shí)質(zhì)執(zhí)行的都是invoke方法
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
						advice.before();								//前置增強(qiáng)
						Object invoke = method.invoke(target, args);	//執(zhí)行目標(biāo)方法
						advice.after();									//后置增強(qiáng)
						System.out.println();
						return invoke;
					}
				});
		
		//代理對(duì)象的方法測(cè)試
		proxyInstance.save();
		
		proxyInstance.print("JDK動(dòng)態(tài)代理");
	}

}

運(yùn)行截圖:

2. 基于cglib的實(shí)現(xiàn)

需要導(dǎo)入Jar包,如果是maven項(xiàng)目,則在pom.xml文件加入如下配置:

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>4.2.4.RELEASE</version>
</dependency>

目標(biāo)類(lèi):

public class Target {
	public void save() {
		System.out.println("save running...");
	}
	
	public void print(String str) {
		System.out.println(str);
	}
}

增強(qiáng)類(lèi):

public class Advice {
	
	public void before() {
		System.out.println("前置增強(qiáng)");
	}

	public void after() {
		System.out.println("后置增強(qiáng)");
	}

}

測(cè)試類(lèi):

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class ProxyTest {

	public static void main(String[] args) {
		final Target target = new Target();
		final Advice advice = new Advice();
		
		//返回值就是動(dòng)態(tài)生成的代理對(duì)象,基于cglib
		//創(chuàng)建增強(qiáng)器
		Enhancer enhancer = new Enhancer();
		
		//設(shè)置父類(lèi)(目標(biāo))
		enhancer.setSuperclass(Target.class);
		
		//設(shè)置回調(diào)
		enhancer.setCallback(new MethodInterceptor() {
			public Object intercept(Object o, Method method, Object[] obj, MethodProxy methodProxy) throws Throwable{
				advice.before();
				Object invoke = method.invoke(target, obj);
				advice.after();
				System.out.println();
				return invoke;
			}
		});
		
		//創(chuàng)建代理對(duì)象
		Target proxy = (Target)enhancer.create();
		
		//測(cè)試代理方法
		proxy.save();
		proxy.print("基于cglib實(shí)現(xiàn)動(dòng)態(tài)規(guī)劃");
		
	}

}

運(yùn)行截圖:

三、為什么要有基于cglib的實(shí)現(xiàn)

使用JDK動(dòng)態(tài)代理實(shí)現(xiàn)時(shí),最大限制是被增強(qiáng)對(duì)象必須實(shí)現(xiàn)接口,并且增強(qiáng)的方法只能是接口中聲明的方法。但在實(shí)際的項(xiàng)目中,可能總是存在對(duì)不實(shí)現(xiàn)業(yè)務(wù)接口的對(duì)象進(jìn)行增強(qiáng)的需求,這時(shí)JDK動(dòng)態(tài)代理將無(wú)能為力。

四、兩種方式的適用場(chǎng)景

JDK動(dòng)態(tài)代理

優(yōu)點(diǎn)

  • 不依賴(lài)第三方j(luò)ar包, 使用方便
  • 隨著JDK的升級(jí),JDK動(dòng)態(tài)代理的性能在穩(wěn)步提升

缺點(diǎn)

  • 只能代理實(shí)現(xiàn)了接口的類(lèi)
  • 執(zhí)行速度較慢

適用場(chǎng)景

  • 如果你的程序需要頻繁、反復(fù)地創(chuàng)建代理對(duì)象,則JDK動(dòng)態(tài)代理在性能上更占優(yōu)。

cglib

優(yōu)點(diǎn)

由于是動(dòng)態(tài)生成字節(jié)碼實(shí)現(xiàn)代理,因此代理對(duì)象的執(zhí)行速度較快, 約為JDK動(dòng)態(tài)代理的1.5 ~ 2倍
可以代理沒(méi)有實(shí)現(xiàn)接口的對(duì)象

缺點(diǎn)

  • 不能代理final類(lèi)
  • 動(dòng)態(tài)生成字節(jié)碼雖然執(zhí)行較快,但是生成速度很慢,根據(jù)網(wǎng)上一些人的測(cè)試結(jié)果,cglib創(chuàng)建代理對(duì)象的速度要比JDK慢10 ~ 15倍。

適用場(chǎng)景

  • 不需要頻繁創(chuàng)建代理對(duì)象的應(yīng)用,如Spring中默認(rèn)的單例bean,只需要在容器啟動(dòng)時(shí)生成一次代理對(duì)象。

以上就是Java 動(dòng)態(tài)代理的多種實(shí)現(xiàn)方式的詳細(xì)內(nèi)容,更多關(guān)于Java 動(dòng)態(tài)代理的實(shí)現(xiàn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot2啟動(dòng)時(shí)執(zhí)行,初始化(或定時(shí)任務(wù))servletContext問(wèn)題

    springboot2啟動(dòng)時(shí)執(zhí)行,初始化(或定時(shí)任務(wù))servletContext問(wèn)題

    這篇文章主要介紹了springboot2啟動(dòng)時(shí)執(zhí)行,初始化(或定時(shí)任務(wù))servletContext問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • SpringCloud負(fù)載均衡spring-cloud-starter-loadbalancer解讀

    SpringCloud負(fù)載均衡spring-cloud-starter-loadbalancer解讀

    這篇文章主要介紹了SpringCloud負(fù)載均衡spring-cloud-starter-loadbalancer使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Mybatis-Plus根據(jù)時(shí)間段去查詢(xún)數(shù)據(jù)的實(shí)現(xiàn)示例

    Mybatis-Plus根據(jù)時(shí)間段去查詢(xún)數(shù)據(jù)的實(shí)現(xiàn)示例

    這篇文章主要介紹了Mybatis-Plus根據(jù)時(shí)間段去查詢(xún)數(shù)據(jù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Java JDBC連接數(shù)據(jù)庫(kù)常見(jiàn)操作總結(jié)

    Java JDBC連接數(shù)據(jù)庫(kù)常見(jiàn)操作總結(jié)

    這篇文章主要介紹了Java JDBC連接數(shù)據(jù)庫(kù)常見(jiàn)操作,結(jié)合實(shí)例形式總結(jié)分析了java基于jdbc連接mysql、Oracle數(shù)據(jù)庫(kù)及連接池相關(guān)操作技巧,需要的朋友可以參考下
    2019-03-03
  • Java深入講解static操作符

    Java深入講解static操作符

    static關(guān)鍵字基本概念我們可以一句話(huà)來(lái)概括:方便在沒(méi)有創(chuàng)建對(duì)象的情況下來(lái)進(jìn)行調(diào)用。也就是說(shuō):被static關(guān)鍵字修飾的不需要?jiǎng)?chuàng)建對(duì)象去調(diào)用,直接根據(jù)類(lèi)名就可以去訪(fǎng)問(wèn),讓我們來(lái)了解一下你可能還不知道情況
    2022-07-07
  • Java實(shí)現(xiàn)將byte[]轉(zhuǎn)換為File對(duì)象

    Java實(shí)現(xiàn)將byte[]轉(zhuǎn)換為File對(duì)象

    這篇文章將通過(guò)一個(gè)簡(jiǎn)單的例子為大家演示Java如何實(shí)現(xiàn) byte[] 轉(zhuǎn)換為 File 對(duì)象,并將其上傳到外部服務(wù)器,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • SpringBoot MyBatis保姆級(jí)整合教程

    SpringBoot MyBatis保姆級(jí)整合教程

    因?yàn)镾pring Boot框架開(kāi)發(fā)的便利性,所以實(shí)現(xiàn)Spring Boot與數(shù)據(jù)訪(fǎng)問(wèn)層框架(例如MyBatis)的整合非常簡(jiǎn)單,主要是引入對(duì)應(yīng)的依賴(lài)啟動(dòng)器,并進(jìn)行數(shù)據(jù)庫(kù)相關(guān)參數(shù)設(shè)置即可
    2022-06-06
  • Java LinkedList的實(shí)現(xiàn)原理圖文詳解

    Java LinkedList的實(shí)現(xiàn)原理圖文詳解

    今天小編就為大家分享一篇關(guān)于Java LinkedList的實(shí)現(xiàn)原理圖文詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • 深入理解java線(xiàn)程通信

    深入理解java線(xiàn)程通信

    開(kāi)發(fā)中不免會(huì)遇到需要所有子線(xiàn)程執(zhí)行完畢通知主線(xiàn)程處理某些邏輯的場(chǎng)景?;蛘呤蔷€(xiàn)程 A 在執(zhí)行到某個(gè)條件通知線(xiàn)程 B 執(zhí)行某個(gè)操作。下面我們來(lái)一起學(xué)習(xí)如何解決吧
    2019-05-05
  • MyBatis中動(dòng)態(tài)sql的實(shí)現(xiàn)方法示例

    MyBatis中動(dòng)態(tài)sql的實(shí)現(xiàn)方法示例

    這篇文章主要給大家介紹了關(guān)于MyBatis中動(dòng)態(tài)sql的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11

最新評(píng)論

白沙| 兰州市| 禹城市| 吴江市| 云梦县| 彭泽县| 靖边县| 义乌市| 漠河县| 策勒县| 高邑县| 和龙市| 北流市| 天水市| 深泽县| 巢湖市| 彰化市| 裕民县| 武宣县| 衡东县| 德安县| 金湖县| 岳西县| 家居| 高淳县| 孟州市| 油尖旺区| 白银市| 仁怀市| 张家口市| 兴城市| 江永县| 乌兰察布市| 安康市| 永安市| 北海市| 车致| 高淳县| 石台县| 广昌县| 龙海市|