非官方解讀代理模式
標簽: 設計模式
代理模式(Proxy) : 代理模式就是多一個代理類出來,替原對象進行一些操作.對方法進行加強.而代理類充當一個中介的角色.我們不直接調用原方法.而是通過代理類進行調用,中間可進行自定義處理.Spring Aop中的通知就是由此而來.代理分為靜態代理,動態代理(Jdk代理),cglib代理三種,下文將進行闡述.
作者是個二吊子,如果描述有誤請指出.
使用場景
我們突然接到一個需求,需要對某些具有特殊身份的數據進行驗證,驗證其合法性.這個時候傳統操作是直接改動原有代碼,增加相應處理邏輯.于是乎我們一頓操作發現有三個地方需要驗證.于是臉滾鍵盤對著三個地方進行代碼改動.一頓輸出后,需求解決,測試,上線,完美閉環.但是第二天我們又接到需求,需要對普通身份的數據也進行驗證.這個時候我們就發現,我們又要操作三個地方.可真是新三年,舊三年,縫縫補補又三年.長此以往我們代碼的可讀性越來越差,維護起來要命.于是引出了代理模式.
靜態代理
uml圖
抽象接口: ITeacherDao, 實現類: TeacherDao, 代理類: TeacherDaoProxy ,客戶端 : Client
/**
* @Description: 接口類
* @Author: gaofan
* @Date: 2020/3/24 12:02
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public interface ITeacherDao {
public void teach();
}
/**
* @Description: 被代理類
* @Author: gaofan
* @Date: 2020/3/24 12:03
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("王老師正在講課");
}
}
/**
* @Description: 代理類
* @Author: gaofan
* @Date: 2020/3/24 12:03
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class TeacherDaoProxy implements ITeacherDao{
private TeacherDao teacherDao;
@Override
public void teach() {
System.out.println("打開課件");
teacherDao.teach();
System.out.println("關閉課件");
}
public TeacherDaoProxy(TeacherDao teacherDao) {
this.teacherDao = teacherDao;
}
}
/**
* @Description: TODO
* @Author: gaofan
* @Date: 2020/3/24 12:05
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class Client {
public static void main(String [] args){
TeacherDaoProxy proxy = new TeacherDaoProxy(new TeacherDao());
proxy.teach();
}
}
類型: 靜態代理
原理: 實現類與代理類均實現抽象類接口,對其方法進行實現.代理類中聚合被代理類,其實現方法中通過聚合代理類調用目標方法.可以在代理類方法中加上我們需要增強的功能與處理.
缺點: 代理類需要實現接口,代碼編譯時已經確定了.
動態代理
通過jdk實現,核心是InvocationHandler , Proxy.newProxyInstance().代理類實現InvocationHandler invoke()方法,我們的增強方法也在這個方法中.通過Proxy.newProxyInstance()產生代理實例進行調用.
uml圖
動態代理與靜態代理的差別: 我們在代理類中并沒有去實現接口,而是通過聚合的方式來實現.動態擴展,讓類與類之間耦合度降低
/**
* @Description: 接口類
* @Author: gaofan
* @Date: 2020/3/24 12:02
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public interface ITeacherDao {
void teach();
void say();
}
/**
* @Description: 具體實現
* @Author: gaofan
* @Date: 2020/3/24 12:03
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("王老師正在講課");
}
@Override
public void say() {
System.out.println("王老師開始吹牛了");
}
}
/**
* @Description: 代理類
* @Author: gaofan
* @Date: 2020/3/24 12:15
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class ProxyFactory implements InvocationHandler {
private Object object;
public ProxyFactory(Object object) {
this.object = object;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass()
.getInterfaces(),this);
// return object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(!method.getName().equals("say")){
System.out.println("打開書本");
}
Object obj = method.invoke(object, args);
if(!method.getName().equals("say")){
System.out.println("關閉書本");
}
return obj;
}
}
/**
* @Description: TODO
* @Author: gaofan
* @Date: 2020/3/24 12:17
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class Client {
public static void main(String [] args){
ProxyFactory factory = new ProxyFactory(new TeacherDao());
ITeacherDao proxyInstance = (ITeacherDao)factory.getProxyInstance();
proxyInstance.say();
proxyInstance.teach();
}
}
類型: 動態代理
原理: 通過Proxy.newProxyInstance()產生實例,自定義實現InvocationHandler的invoke()方法進行增強.
缺點: 依賴接口實現,必須要有接口類
cglib代理
通過非jdk自帶jar實現,能夠對類進行加強,并不僅限于接口
uml圖
動態代理依賴接口實現,而cglib則是直接對類下手了,內部實現應該是字節碼.留著后邊探索了
/**
* @Description: 被代理類
* @Author: gaofan
* @Date: 2020/3/24 12:47
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class TeacherDao {
public void teach() {
System.out.println("王老師正在講課");
}
public void say() {
System.out.println("王老師開始吹牛了");
}
}
/**
* @Description: 代理類
* @Author: gaofan
* @Date: 2020/3/24 12:48
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance(){
// 創建工具類
Enhancer enhancer = new Enhancer();
// 設置父類
enhancer.setSuperclass(target.getClass());
// 設置回調函數
enhancer.setCallback(this);
// 創建子類對象,即代理對象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib 代理開始了");
Object obj = method.invoke(target, objects);
System.out.println("cglib 代理結束了");
return obj;
}
}
/**
* @Description: TODO
* @Author: gaofan
* @Date: 2020/3/24 12:48
* @Copyright: 2020 www.withu.top Inc. All rights reserved.
**/
public class Client {
public static void main(String[] args) {
TeacherDao teacherDao = new TeacherDao();
ProxyFactory factory = new ProxyFactory(teacherDao);
TeacherDao dao = (TeacherDao) factory.getProxyInstance();
dao.teach();
dao.say();
}
}
原理: 代理類實現MethodInterceptor ,實現其intercept 方法(攔截器),通過Enhancer 工具類設置父類,設置回調,創建子類對象并返回實例.客戶端通過返回實例進行調用.
優點: 直接對類增強.對接口沒有依賴
本文借鑒尚硅谷Java設計模式,韓順平圖解java,傳送門
智能推薦
Spring AOP編程官方文檔解讀之代理機制
系列文章目錄 第一章 : Spring AOP編程官方文檔解讀之切點 第二章 : Spring AOP編程官方文檔解讀之增強 第三章 : Spring AOP編程官方文檔解讀之增強方法參數 第四章 : Spring AOP編程官方文檔解讀之引介增強 第五章 : Spring AOP編程官方文檔解讀之另類切面Advisor 第六章 : Spring AOP編程官方文檔解讀之代理機制 文章目錄 系列文...
wmctf web部分wp(非官方qwq
web_checkin 隊友@小白菜 隨便試了一個content=/flag就出flag了(后期知道是因為文件名的非預期 Make PHP Great Again 看著短短的五行代碼,實在難做嚶嚶嚶 后來得知是session.upload_progress(后知后覺 那就開整! 參考文章了https://www.freebuf.com/news/202819.html 改了一下就開跑! 然后就出來...
YEOMAN官方文檔非官方翻譯~快速使用(codelab)
在25分鐘的 codelab(編碼實驗) 中,你將在 Yeoman、FountainJS 的幫助下,通過腳手架構建起一個功能完整的web應用。這個簡單的應用將會用 React、Angular2、Angular1 來編寫。 不知道 React 或者 Angular?沒關系,我們將會幫您渡過難關。然而,我們必須假定你先前已經有了一些 JavaScript 的編程經驗。 通過Yeoman構建這個簡單的應...
Qt 圖像疊加模式[composition Modes]官方例子 源碼解讀
前言: 看 qt 的例子 看到個有意思的 圖片質量有壓縮 看起來不美 這個代碼 比我們平常看到的要復雜一點 能學到東西 我把源碼看了一下 在這里在仔細整理說一下 composition 項目結構 一個 shared 文件夾 幾個類 注意 這個 hoverpoints 類沒有用到 因為我沒有開啟 opengl 兩個資源文件 一些美化控件的圖片 兩種 底色圖片 就是那個背景花 一個 html 里面是介...
SpringBoot非官方教程 | 第十九篇: 驗證表單信息
轉載請標明出處: http://blog.csdn.net/forezp/article/details/71023817 本文出自方志朋的博客 這篇文篇主要簡述如何在springboot中驗證表單信息。在springmvc工程中,需要檢查表單信息,表單信息驗證主要通過注解的形式。 構建工程 創建一個springboot工程,由于用到了 web 、thymeleaf、validator、el,引入...
猜你喜歡
SpringBoot非官方教程 | 第十二篇:springboot集成apidoc
轉載請標明出處: http://blog.csdn.net/forezp/article/details/71023579 本文出自方志朋的博客 首先聲明下,apidoc是基于注釋來生成文檔的,它不基于任何框架,而且支持大多數編程語言,為了springboot系列的完整性,所以標了個題。 一、apidoc簡介 apidoc通過在你代碼的注釋來生成api文檔的。它對代碼沒有侵入性,只需要你寫好相關的...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...