常見的代理模式是我們業(yè)務開發(fā)時候經常會用到的一種設計模式液走。代理模式給某一個目標對象提供一個代理對象液南,并由代理對象控制對原目標對象的引用浪讳,完成目標對象的方法吸耿,并且在目標對象方法的前后制妄,進行邏輯的增強掸绞。通俗的來講代理模式就是我們生活中常見的中介。
代理模式在業(yè)務開發(fā)中一般有靜態(tài)代理和動態(tài)代理耕捞,下面舉一個生活中的例子來說明靜態(tài)代理與動態(tài)代理衔掸。
普通人person是一個接口,他有買東西和找工作兩種功能
目標類是son俺抽,他實現(xiàn)了Person接口敞映,因此有了買東西和找工作的兩個方法
此時Son想找一個代理來幫助他更好的完成這兩件事情。
首先是靜態(tài)代理:
我們可以看到磷斧,靜態(tài)代理將接口方法振愿,目標對象都要寫進去,并且提前就要聲明要幫誰代理弛饭,所以如果此時不光son需要代理冕末,girl,boy等等目標類都要求代理的話侣颂,需要寫出各個目標對象一一對應的代理類档桃,所以整體下來還是相當麻煩的。靜態(tài)代理其實是在編譯時就將接口憔晒、實現(xiàn)類藻肄、代理類一股腦兒全部手動完成。
為了彌補靜態(tài)代理的不足拒担,我們想只寫一次嘹屯,等真正運行時在判斷哪個目標對象需要代理。這時候就需要動態(tài)代理了澎蛛。動態(tài)代理分為JDK動態(tài)代理和CgLib動態(tài)代理抚垄。
先看JDK動態(tài)代理:
我們看到,JDK動態(tài)代理類首先需要實現(xiàn)InvocationHandler接口,然后完成invoke方法呆馁,也是代理邏輯增強的方法桐经。JDK動態(tài)代理一開始并不確定誰是目標類,而是利用反射原理得到目標類的類加載器浙滤,接口阴挣,并且利用這些作為參數來生成代理對象,然后在測試時候才將目標類確認纺腊,作為參數傳給代理實例畔咧。
JDK動態(tài)代理擁有局限性,那就是必須面向接口編程揖膜,沒有接口就無法實現(xiàn)代理誓沸,我們也不可能為了代理而為每個需要實現(xiàn)代理的類強行添加毫無意義的接口,這時我們需要Cglib壹粟,這種依靠繼承來實現(xiàn)動態(tài)代理的方式拜隧,不再要求我們必須要有接口。
CgLib動態(tài)代理:
CgLib動態(tài)代理要實現(xiàn)MethodInterceptor接口趁仙,他有一個方法intercept洪添,其實是攔截的意思,也就是說業(yè)務邏輯的增強在這里進行雀费。CgLib動態(tài)代理生成代理的方式是利用Enhancer增強類干奢,并將目標類設置為enhancer的父類,以此來得到目標類的接口盏袄,方法信息等等忿峻。