百度云 做網(wǎng)站/濟南百度推廣開戶
代理可以進一步劃分為靜態(tài)代理和動態(tài)代理,代理模式在實際的生活中場景很多,例如中介、律師、代購等行業(yè),都是簡單的代理邏輯,在這個模式下存在兩個關鍵角色:
目標對象角色:即代理對象所代表的對象。
代理對象角色:內(nèi)部含有目標對象的引用,可以操作目標對象
一、靜態(tài)代理
目標對象角色
public class Target {public void execute(){System.out.println("Target execute...");}
}
代理對象角色
public class ProxyObj {private Target target;public ProxyObj(Target target){this.target=target;}public void invoke(){before();target.execute();after();}public void before(){System.out.println("before...");}public void after(){System.out.println("after...");}
}
public class Proxy {public static void main(String[] args) {Target target = new Target();ProxyObj proxy = new ProxyObj(target);proxy.invoke();}
}
代理模式的本質(zhì)是在目標對象的方法前后置入增強操作
二、動態(tài)代理
首先看兩個核心類,這里簡述下概念,看完基本過程再細聊:
-
Proxy-創(chuàng)建代理對象,核心參數(shù):
- ClassLoader:(目標類)加載器;
- Interfaces:(目標類)接口數(shù)組;
- InvocationHandler:代理調(diào)用機制;
-
InvocationHandler-代理類調(diào)用機制:
- invoke:這個上篇說的反射原理;
- method:反射類庫中的核心API;
目標對象和接口
interface IUser {Integer update (String name) ;
}
class UserService implements IUser {@Overridepublic Integer update(String name) {Integer userId = 99 ;System.out.println("UserId="+userId+";updateName="+name);return userId ;}
}
代理對象執(zhí)行機制
class UserHandler implements InvocationHandler {private Object target ;public UserHandler (Object target){this.target = target ;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before()...");Object result = method.invoke(target, args);System.out.println("after()...");return result;}
}
具體使用:
public class Proxy02 {public static void main(String[] args) {/** 生成$Proxy0的class文件*/System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");/** 目標對象信息*/IUser userService = new UserService();ClassLoader classLoader = userService.getClass().getClassLoader();Class<?>[] interfaces = UserService.class.getInterfaces() ;/** 創(chuàng)建代理對象*/InvocationHandler userHandler = new UserHandler(userService);/** 代理類對象名* proxyClassName=com.java.proxy.$Proxy0*/String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();System.out.println("proxyClassName="+proxyClassName);/** 具體業(yè)務實現(xiàn)模擬*/IUser proxyUser1 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);IUser proxyUser2 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);proxyUser1.update("cicada") ;proxyUser2.update("smile") ;}
}
?
JDK源碼
IUser proxyUser = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
Proxy提供的靜態(tài)方法newProxyInstance()
,通過各個參數(shù)的傳入,構(gòu)建一個新的代理Class對象,即$Proxy0類的結(jié)構(gòu)信息,這里再回首看下三個核心參數(shù):
-
ClassLoader:基于JVM運行過程,所以需要獲取目標類UserService的類加載器;
-
Interfaces:目標類UserService實現(xiàn)的接口,從面向?qū)ο髞砜紤],接口與實現(xiàn)分離,代理類通過實現(xiàn)IUser接口,模擬目標類的需求;
-
InvocationHandler:代理類提供的功能封裝即UserHandler,可以在目標方法調(diào)用前后做增強處理