漫談代理模式

本文首發於泊浮目的專欄: https://segmentfault.com/blog...

前言

代理模式是在編程中很是常見的設計模式.筆者在面試的過程當中也常常會問到相關的問題,可是不少同窗答的並不盡人意.在這篇文章中,筆者想和你們聊聊代理模式的應用及一些實踐.程序員

What

先來一張圖
面試

咱們能夠很明顯的看到,代理和客戶端發生了耦合,而目標端則與客戶端解耦.spring

Why

上文提到了一點,鬆耦合.而在任何設計模式中,他們的目的都在如下範圍內:編程

  1. 減小代碼冗餘度,提升代碼複用性
  2. 鬆耦合

這裏提到了代碼的複用性,也能夠多嘴一句,代理模式能夠幫助咱們實現The Open Closed Principle.segmentfault

在這裏,咱們能夠舉一個例子.Target多是一位不錯的程序員,client是一家公司.在整個招聘流程中,若是Proxy是獵頭,有些獵頭則可能會想辦法幫程序員提升身價.而若是Proxy是Hr,則可能會來殺殺價.而程序員走的流程可能一直是同樣的:設計模式

  1. 電面
  2. 到面
  3. 籤合同

咱們能夠把不一樣的行爲(討價還價的特殊技巧)寫在不一樣的Proxy裏(HrProxy or 獵頭Proxy),而咱們的程序員只要專心走流程就好了.網絡

How

以Java中最經常使用的框架——Spring爲例.Spring最主要提供了2個功能:框架

  • IOC(Inversion of Control)
  • AOP(Aspect Oriented Programming)

而咱們知道,Spring的AOP本質上是經過代理模式來作的.接下來咱們來詳細聊聊Spring提供的4種類型的AOP支持:spa

  • 基於代理的經典Spring AOP;
  • 純POJO切面;
  • @AspectJ註解驅動的切面;
  • 注入式AspectJ切面(適用於Spring各版本)。

前三種都是Spring AOP實現的變體,Spring AOP構建在動態代理基礎之上,所以,Spring對AOP的支持侷限於方法攔截。設計

而SpringAOP支持兩種模式的動態代理,JDK Proxy和cglib.當Spring發現目標被代理類實現就接口時,則用JDK Proxy來實現.

  • JDK Proxy不徹底經過反射來作,也有ASM進行字節碼操做的.本質是經過接口約定來作的
  • cglib徹底經過ASM字節碼來作.本質經過繼承的方式實現

代碼大概長這樣:

//spring aop 生成的代理
public class SpringAopTargetProxy extends Target{
    public void  operate(){
            //spring aop method1...
            super.operate();
           //spring aop method2...
    }
}

而AspectJ是經過編譯時編織來作的,即在編譯時插代碼進去.因此能夠認爲它基於靜態代理來作AOP.

基於以上,咱們也能夠推導出SpringAOP對於finalorstatic方法是無效的.

callexecution有什麼區別呢?
  • call就是在調用這個方法的地方插入代碼
  • execution就是在調用這個方法的前面插入代碼

代理模式的變化形式

以前,咱們根據代理生成的時機來區分了靜態代理和動態代理.而根據使用方式,常見則有兩類:

  • Virtual Proxy:只有當真正須要實例時,它才生成和初始化實例
  • Remote Proxy:遠程代理可讓咱們沒必要關心RealSubject角色是否在網絡上,而是像調本地方法同樣調用它的方法.Java的RMI(Remote Method Invocation)就至關於遠程代理.

相似的設計模式

Adapter

Adapter模式適配了兩種具備不一樣接口(API)的對象,以使它們能夠一同工做。而在Proxy模式中, Proxy角色與RealSubject角色的接口(API )是相同的(透明性)。

Decorator

Decorator模式與Proxy模式在實現上很類似(好比API的一致性),不過它們的使用目的不一樣——Decorator模式的目的在於增長新的功能。而在Proxy模式中,與增長新功能相比,它更注重經過設置代理人的方式來減輕本人的工做負擔.

相關文章
相關標籤/搜索