自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java實(shí)現(xiàn)代理模式的三種方式

開發(fā) 前端
代理模式是項(xiàng)目中常用的一種設(shè)計(jì)模式。提供了間接訪問(wèn)目標(biāo)對(duì)象的一種方式;即通過(guò)代理對(duì)象訪問(wèn)目標(biāo)對(duì)象。這樣做的好處是,可以在不改變?cè)心繕?biāo)對(duì)象的基礎(chǔ)上,對(duì)目標(biāo)對(duì)象增加額外的擴(kuò)展功能。

什么是代理模式

代理模式是項(xiàng)目中常用的一種設(shè)計(jì)模式。提供了間接訪問(wèn)目標(biāo)對(duì)象的一種方式;即通過(guò)代理對(duì)象訪問(wèn)目標(biāo)對(duì)象。

這樣做的好處是,可以在不改變?cè)心繕?biāo)對(duì)象的基礎(chǔ)上,對(duì)目標(biāo)對(duì)象增加額外的擴(kuò)展功能。

代理模式又分為靜態(tài)代理、jdk動(dòng)態(tài)代理、cglib動(dòng)態(tài)代理三種實(shí)現(xiàn)方式。

三種實(shí)現(xiàn)方式各有優(yōu)點(diǎn),以及適用的場(chǎng)景。

一、靜態(tài)代理

被代理對(duì)象與代理對(duì)象需要實(shí)現(xiàn)相同的接口或者是繼承相同父類,因此要定義一個(gè)接口或抽象類。

/**代理接口*/
public interface IHello {
String hi(String key);
}
/**代理接口實(shí)現(xiàn)類*/
public class HelloImpl implements IHello {
@Override
public String hi(String key) {
String str = "hello:" + key;
System.out.println("HelloImpl! " + str);
return str;
}
}
/**靜態(tài)代理類*/
public class HelloStaticProxy implements IHello {

private IHello hello;

public HelloStaticProxy(IHello hello) {
this.hello = hello;
}

@Override
public String hi(String key) {
System.out.println(">>> static proxy start");
String result = hello.hi(key);
System.out.println(">>> static proxy end");
return result;
}
}
/**測(cè)試*/
public class DemoTest {

public static void main(String[] args) {
IHello helloProxy = new HelloStaticProxy(new HelloImpl());
helloProxy.hi("world");
}
}

輸出結(jié)果:

>>> static proxy start
HelloImpl! hello:world
>>> static proxy end

二、jdk動(dòng)態(tài)代理

jdk動(dòng)態(tài)代理是基于接口的一種代理方式,目標(biāo)對(duì)象一定要實(shí)現(xiàn)接口。

原理是,利用反射機(jī)制,動(dòng)態(tài)生成匿名類繼承Proxy類并且實(shí)現(xiàn)了要代理的接口,由于java不支持多繼承,所以JDK動(dòng)態(tài)代理不能代理類。

/**代理接口*/
public interface IHello {
String hi(String key);
}
/**代理接口實(shí)現(xiàn)類*/
public class HelloImpl implements IHello {
@Override
public String hi(String key) {
String str = "hello:" + key;
System.out.println("HelloImpl! " + str);
return str;
}
}


/**jdk動(dòng)態(tài)代理類*/
public class JdkProxy implements InvocationHandler {

private Object target;

public JdkProxy(Object target) {
this.target = target;
}

/**
* 獲取被代理接口實(shí)例對(duì)象
*
* @param <T>
* @return
*/
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(">>> JdkProxy start");
Object result = method.invoke(target, args);
System.out.println(">>> JdkProxy end");
return result;
}
}

/**測(cè)試*/
public class Demo2Test {

public static void main(String[] args) {
JdkProxy proxy = new JdkProxy(new HelloImpl());
IHello helloProxy = proxy.getProxy();
helloProxy.hi(" jdk proxy !");
}
}

輸出結(jié)果:

>>> JdkProxy start
HelloImpl! hello: jdk proxy !
>>> JdkProxy end

三、cglib動(dòng)態(tài)代理

目標(biāo)對(duì)象可以不用實(shí)現(xiàn)接口,不能針對(duì)final類進(jìn)行代理。

原理是,動(dòng)態(tài)生成class繼承目標(biāo)對(duì)象。

使用cglib必須引入對(duì)應(yīng)的jar包。

 <dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.7</version>
</dependency>
/**目標(biāo)類*/
public class HelloImpl {
public String hi(String key) {
String str = "hello:" + key;
System.out.println("HelloImpl! " + str);
return str;
}
}

/**cglib代理類*/
public class CglibProxy implements InvocationHandler {

private Object target;

/**
* 獲取被代理接口實(shí)例對(duì)象
*/
public <T> T getProxy() {
//1創(chuàng)建增強(qiáng)器對(duì)象
Enhancer e = new Enhancer();
//2設(shè)置增強(qiáng)器的類加載器
e.setClassLoader(target.getClass().getClassLoader());
//3設(shè)置代理對(duì)象父類類型
e.setSuperclass(target.getClass());
//4設(shè)置回調(diào)函數(shù)
e.setCallback(this);
//5創(chuàng)建代理對(duì)象
return (T) e.create();
}

public CglibProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(">>> cglib start");
Object obj = method.invoke(target, args);
System.out.println(">>> cglib end");
return obj;
}
}

/**測(cè)試*/
public class Demo3Test {

public static void main(String[] args) {
HelloImpl hello = new HelloImpl();
CglibProxy cglibProxy = new CglibProxy(hello);
HelloImpl proxy = cglibProxy.getProxy();
proxy.hi(" cglib ");
}
}

輸出結(jié)果:

>>> cglib start
HelloImpl! hello: cglib
>>> cglib end

四、總結(jié)

靜態(tài)代理,代理類必須非常明確,所以無(wú)法做到通用,但是效率也是最高的。

jdk動(dòng)態(tài)代理,必須基于接口代理,有一定局限性;動(dòng)態(tài)生成字節(jié)碼文件,可以用于通用業(yè)務(wù)(性能日志等)。

cglig動(dòng)態(tài)代理,也是動(dòng)態(tài)生成字節(jié)碼文件,生成的代理類繼承了目標(biāo)對(duì)象。

spring aop默認(rèn)代理策略是:如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,則使用jdk動(dòng)態(tài)代理,否則使用cglib代理。

jdk8之后,jdk動(dòng)態(tài)代理效率要高于cglib代理?。

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2018-04-02 14:29:18

Java多線程方式

2014-12-31 17:42:47

LBSAndroid地圖

2021-06-24 08:52:19

單點(diǎn)登錄代碼前端

2021-11-05 21:33:28

Redis數(shù)據(jù)高并發(fā)

2010-03-12 17:52:35

Python輸入方式

2023-12-04 09:31:13

CSS卡片

2024-07-01 12:42:58

2024-07-08 09:03:31

2022-01-17 08:19:51

Javascript 接口前端

2022-01-20 08:38:02

Java接口Lambda

2012-07-17 09:16:16

SpringSSH

2010-09-07 16:31:27

CSS

2015-09-14 09:31:44

結(jié)對(duì)設(shè)計(jì)

2022-06-06 13:41:27

區(qū)塊鏈商業(yè)活動(dòng)數(shù)字技術(shù)

2024-05-27 00:20:00

2024-08-13 08:25:16

C#外部程序方式

2019-11-20 18:52:24

物聯(lián)網(wǎng)智能照明智能恒溫器

2020-11-01 17:10:46

異步事件開發(fā)前端

2021-03-07 10:17:40

RDMA網(wǎng)絡(luò)傳輸網(wǎng)絡(luò)協(xié)議

2022-05-27 11:33:02

前端代碼設(shè)計(jì)模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)