0、前言
代理模式可以在不修改被代理對(duì)象的基礎(chǔ)上,通過(guò)擴(kuò)展代理類,進(jìn)行一些功能的附加與增強(qiáng)。
1、靜態(tài)代理
靜態(tài)代理是一種代理模式的實(shí)現(xiàn)方式,它在編譯期間就已經(jīng)確定了代理對(duì)象,需要為每一個(gè)被代理對(duì)象創(chuàng)建一個(gè)代理類。靜態(tài)代理的實(shí)現(xiàn)比較簡(jiǎn)單,但是每個(gè)被代理對(duì)象都需要?jiǎng)?chuàng)建一個(gè)代理類,因此在代理對(duì)象比較多時(shí),會(huì)導(dǎo)致代碼幾余和維護(hù)成本增加。
靜態(tài)代理有兩種實(shí)現(xiàn),繼承和聚合兩種模式。
1.1、繼承模式
需要定義接口或者父類,被代理對(duì)象與代理對(duì)象一起實(shí)現(xiàn)相同的接口或者繼續(xù)相同父類,代理對(duì)象繼承目標(biāo)對(duì)象,重新目標(biāo)對(duì)象的方法。
?目標(biāo)對(duì)象:
package proxy.staticproxy.extends_model;
//目標(biāo)對(duì)象
public class UserService {
public void login(){
System.out.println("login success");
}
}
代理類:
package proxy.staticproxy.extends_model;
//代理對(duì)象
public class UserServiceProxy extends UserService{
public void login(){
System.out.println("開(kāi)始執(zhí)行--------------");
super.login();
}
}
?測(cè)試類:
package proxy.staticproxy;
import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;
public class Test {
@org.junit.Test
public void extends_model(){
UserServiceProxy proxy = new UserServiceProxy();
proxy.login();
}
// 待代理類來(lái)處理
/// 場(chǎng)景:當(dāng)不想改動(dòng)被代理類的業(yè)務(wù)邏輯,在處理開(kāi)始和結(jié)束分別加上時(shí)間顯示
/// 處理核心邏輯:需要實(shí)現(xiàn)被代理類的接口及方法,在實(shí)現(xiàn)方法中田間需要添加的業(yè)務(wù)處理邏輯
@org.junit.Test
public void implements_model(){
// 創(chuàng)建被代理類的對(duì)象
IFactory word = new FactoryOne();
// 創(chuàng)建代理類的對(duì)象
IFactory proxyPaperFactory = new FactoryOneProxy(word);
proxyPaperFactory.production();
}
// 直接調(diào)用被代理類業(yè)務(wù)處理
@org.junit.Test
public void test01(){
// 創(chuàng)建被代理類的對(duì)象
IFactory word = new FactoryOne();
word.production();
}
}
?執(zhí)行結(jié)果:
開(kāi)始執(zhí)行--------------
login success
1.2、聚合模式
Subject:抽象主題角色,抽象主題類可以是抽象類,也可以是接口,是一個(gè)最普通的業(yè)務(wù)類型定義,無(wú)特殊要求。
RealSubject:具體主題角色,也叫被委托角色、被代理角色。是業(yè)務(wù)邏輯的具體執(zhí)行者。
Proxy:代理主題角色,也叫委托類、代理類。它把所有抽象主題類定義的方法給具體主題角色實(shí)現(xiàn),并且在具體主題角色處理完畢前后做預(yù)處理和善后工作。?
Subject 接口:
package proxy.staticproxy.implements_model;
public interface IFactory {
void production();
}
?RealSubject 類:
package proxy.staticproxy.implements_model;
public class FactoryOne implements IFactory {
@Override
public void production() {
System.out.println(" 被代理類,開(kāi)始初始化 ");
System.out.println(" 生產(chǎn)筆記本、鼠標(biāo)、鍵盤等等 ");
System.out.println(" 被代理類處理完成 ");
}
}
Proxy 類:
package proxy.staticproxy.implements_model;
public class FactoryOneProxy implements IFactory {
private IFactory factory; // 用被代理類對(duì)象進(jìn)行實(shí)例化
public FactoryOneProxy(IFactory factory) {
this.factory = factory;
}
@Override
public void production() {
System.out.println(" 代理開(kāi)始工作 ,在此可以添加處理邏輯");
factory.production();
System.out.println(" 代理結(jié)束工作 ,在此可以添加處理邏輯");
}
}
?測(cè)試類:
package proxy.staticproxy;
import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;
public class Test {
@org.junit.Test
public void extends_model(){
UserServiceProxy proxy = new UserServiceProxy();
proxy.login();
}
// 待代理類來(lái)處理
/// 場(chǎng)景:當(dāng)不想改動(dòng)被代理類的業(yè)務(wù)邏輯,在處理開(kāi)始和結(jié)束分別加上時(shí)間顯示
/// 處理核心邏輯:需要實(shí)現(xiàn)被代理類的接口及方法,在實(shí)現(xiàn)方法中田間需要添加的業(yè)務(wù)處理邏輯
@org.junit.Test
public void implements_model(){
// 創(chuàng)建被代理類的對(duì)象
IFactory word = new FactoryOne();
// 創(chuàng)建代理類的對(duì)象
IFactory proxyPaperFactory = new FactoryOneProxy(word);
proxyPaperFactory.production();
}
// 直接調(diào)用被代理類業(yè)務(wù)處理
@org.junit.Test
public void test01(){
// 創(chuàng)建被代理類的對(duì)象
IFactory word = new FactoryOne();
word.production();
}
}
運(yùn)行結(jié)果:
代理開(kāi)始工作 ,在此可以添加處理邏輯
被代理類,開(kāi)始初始化
生產(chǎn)筆記本、鼠標(biāo)、鍵盤等等
被代理類處理完成
代理結(jié)束工作 ,在此可以添加處理邏輯
2、動(dòng)態(tài)代理
動(dòng)態(tài)代理是一種代理模式的實(shí)現(xiàn)方式,它在運(yùn)行期間根據(jù)需要?jiǎng)討B(tài)生成代理對(duì)象,無(wú)需手動(dòng)編寫代理類,可以減少代碼幾余和維護(hù)成本。動(dòng)態(tài)代理適用于需要代理的對(duì)象數(shù)量較多,代理類實(shí)現(xiàn)對(duì)靈活的場(chǎng)景,例Spring框架中的Spring AOP(面向切面編程)功能。
動(dòng)態(tài)代理的實(shí)現(xiàn)方式也有兩種,JDK動(dòng)態(tài)代理和CGLB動(dòng)態(tài)代理兩種模式。本文重點(diǎn)介紹JDK動(dòng)態(tài)代理,
在JDK中,有一個(gè)Proxy類(名詞,代理人)。Proxy類是專門完成代理的操作類,可以通過(guò)此類為一個(gè)或多個(gè)接口動(dòng)態(tài)的生成實(shí)現(xiàn)類。Proxy類提供的有一個(gè)靜態(tài)方法:newProxyInstance()方法給我們的目標(biāo)對(duì)象(委托對(duì)象)返回一個(gè)代理對(duì)象。
核心方法:newProxyInstance方法的三個(gè)參數(shù),按照順序分別是 ClassLoader (類加載器),interfaces(一組接口,接口數(shù)組),InvocationHandler(調(diào)用處理器)。
ClassLoader (類加載器)
定義了由哪個(gè)classLoader對(duì)象來(lái)對(duì)生成的代理對(duì)象進(jìn)行加載。
接口數(shù)組:
一個(gè)Interface對(duì)象的數(shù)組,表示將要給我需要代理的對(duì)象提供一組什么接口,如果我提供了一組接口給它,那么這個(gè)代理對(duì)象就宣稱實(shí)現(xiàn)了該接口(多態(tài)),這樣我就能調(diào)用這組接口中的方法了。
調(diào)用處理器:
一個(gè)InvocationHandler接口,表示代理實(shí)例的調(diào)用處理程序?qū)崿F(xiàn)的接口。每個(gè)代理實(shí)例都具有一個(gè)關(guān)聯(lián)的調(diào)用處理程席。對(duì)代理實(shí)例調(diào)用方法時(shí),將對(duì)方法調(diào)用進(jìn)行編碼并將其指派到它的調(diào)用處理程序的 invoke 方法(傳入InvocationHandler接口的子類)。
對(duì)象接口:
package proxy.dynamicproxy.v3;
public interface IAnimal {
public void run();
public void eat();
public void sleep();
}
被代理類<Cat>:
package proxy.dynamicproxy.v3;
public class Cat implements IAnimal{
@Override
public void run() {
System.out.println("Cat Run invoking!!!");
}
@Override
public void eat() {
System.out.println("Cat eat invoking!!!");
}
@Override
public void sleep() {
System.out.println("Cat sleep invoking!!!");
}
}
被代理類<Dog>:?
package proxy.dynamicproxy.v3;
public class Dog implements IAnimal{
@Override
public void run() {
System.out.println("Dog Run invoking!!!");
}
@Override
public void eat() {
System.out.println("Dog eat invoking!!!");
}
@Override
public void sleep() {
System.out.println("Dog sleep invoking!!!");
}
}
?代理類工具類:
package proxy.dynamicproxy.v3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtils {
public Object object;
public ProxyUtils(Object object) {
this.object = object;
}
public Object createProxyObj(){
// 動(dòng)態(tài)代理 顧名思義 針對(duì)接口動(dòng)態(tài)生成代理類處理業(yè)務(wù)邏輯
// 返回動(dòng)態(tài)代理
/*
ClassLoader loader, 要實(shí)現(xiàn)接口的類加載器
Class<?>[] interfaces,接口類
InvocationHandler h 處理類
* **/
ClassLoader loader = object.getClass().getClassLoader();
// Class<?>[] interfaces = new Class[]{argObj.getClass()}; // 當(dāng)是接口
Class<?>[] interfaces = object.getClass().getInterfaces(); // 當(dāng)是類直接獲取對(duì)應(yīng)的接口方法;
InvocationHandler handler = new IFactoryInvocationHandler();
Object object = Proxy.newProxyInstance(loader, interfaces, handler);
return object;
}
public class IFactoryInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("IFactoryInvocationHandler invoke Before!!!");
Object rtn = method.invoke(object, args);
System.out.println("IFactoryInvocationHandler invoke After!!!");
return rtn;
}
}
}
測(cè)試類:
package proxy.dynamicproxy;
import proxy.dynamicproxy.v3.Cat;
import proxy.dynamicproxy.v3.IAnimal;
import proxy.dynamicproxy.v3.ProxyUtils;
public class Test {
@org.junit.Test
public void v3_common_test() {
// 實(shí)例化代理工具類
ProxyUtils proxyUtils = new ProxyUtils(new Cat());
// 創(chuàng)建代理對(duì)象
IAnimal animal = (IAnimal)proxyUtils.createProxyObj();
// 調(diào)用被代理類的方法
animal.eat();
System.out.println("========================================================");
animal.run();
System.out.println("========================================================");
animal.sleep();
System.out.println("========================================================");
}
}
?運(yùn)行結(jié)果:
IFactoryInvocationHandler invoke Before!!!
Cat eat invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat Run invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat sleep invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
Process finished with exit code 0
3、動(dòng)態(tài)代理原理
JDK動(dòng)態(tài)代理是一種實(shí)現(xiàn)代理模式的方式。它利用Java的反射機(jī)制,在運(yùn)行時(shí)動(dòng)態(tài)地創(chuàng)建代理對(duì)象,實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象的代理。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-680610.html
JDK動(dòng)態(tài)代理的原理如下:
定義接口:首先需要定義一個(gè)接口,用于描述目標(biāo)對(duì)象和代理對(duì)象的共同行為。
實(shí)現(xiàn)InvocationHandler接口:創(chuàng)建一個(gè)實(shí)現(xiàn)InvocationHandler接口的代理處理器類,該類負(fù)責(zé)對(duì)目標(biāo)對(duì)象的方法進(jìn)行代理。
獲取代理類:通過(guò)java.lang.reflect.Proxy的靜態(tài)方法newProxyInstance()創(chuàng)建代理類,該方法需要傳入ClassLoader、接口數(shù)組和InvocationHandler實(shí)例。
調(diào)用代理對(duì)象:通過(guò)代理對(duì)象調(diào)用方法時(shí),實(shí)際上是調(diào)用InvocationHandler的invoke()方法。
在invoke()方法中,可以進(jìn)行一些額外的操作,比如在調(diào)用目標(biāo)方法之前進(jìn)行預(yù)處理、在調(diào)用目標(biāo)方法后進(jìn)行后處理等。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-680610.html
4、總結(jié)
到了這里,關(guān)于溫故知新之:代理模式,靜態(tài)代理和動(dòng)態(tài)代理(JDK動(dòng)態(tài)代理)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!