代理模式在java開發總是一種比較常見的設計模式。設計目的皆在爲服務類與客戶類之間插入其他功能,插入的功能對於調用者來說是透明的,起到僞裝控制的作用。
今天整理了下靜態代理模式和動態代理模式的一些簡單的知識點。
一、Uml簡圖如下:
二、代理模式分爲兩類:靜態代理和動態代理及批量代理(aop)
1.靜態代理
爲某個對象提供一個代理,代理角色固定,以控制對這個對象的訪問。 代理類和委託類有共同的父類或父接口,這樣在任何使用委託類對象的地方都可以用代理對象替代。代理類負責請求的預處理、過濾、將請求分派給委託類處理、以及委託類執行完請求後的後續處理。
- 定義一個共同的父接口
package com.shuaiwen.aop;
/**
* 接口 抽象角色
* 定義行爲
* @author acer
*
*/
public interface Marry {
public void toMarry();
}
2.定義一個真實角色(委託類)實現上面那個接口
package com.shuaiwen.aop;
/**
* 真實角色
* 和代理角色實現同一個接口
* @author acer
*
*/
public class You implements Marry{
@Override
public void toMarry() {
System.out.println("終於等到你,還好沒放棄。。");
}
}
3.定義一個代理對象(代理類)實現marry父接口
package com.shuaiwen.aop;
/**
* 創建代理對象
* 和真是角色持有相同的接口
* @author acer
* 代理類
* 1.與真實角色具有相同行爲
* 2.持有真實角色的引用
* 3.增強真實角色的行爲
*/
public class MarryCompany implements Marry{
//目標角色的引用
private Marry target;
// 構造方法 傳入真實角色
public MarryCompany(Marry target) {
super();
this.target = target;
}
public void before(){
System.out.println("結婚前的佈置。。。");
}
@Override
public void toMarry() {
// 增強真實角色行爲
before();
target.toMarry();
after();
}
public void after(){
System.out.println("結婚後的感言。。。");
}
}
4.測試類
package com.shuaiwen.test;
import com.shuaiwen.aop.MarryCompany;
import com.shuaiwen.aop.You;
public class Test01 {
public static void main(String[] args) {
// 構造代理角色同時傳入真實角色
MarryCompany marryCompany=new MarryCompany(new You());
marryCompany.toMarry();
}
}
結果爲:
結婚前的佈置。。。
終於等到你,還好沒放棄。。
結婚後的感言。。。
2.動態代理
相比於靜態代理,動態代理在創建代理對象上更加的靈活,它會根據需要通過反射機制在程序運行期動態的爲目標對象創建代理對象,代理的行爲可以代理多個方法,即滿足生產需要的同時又達到代碼通用的目的。
動態代理的實現有兩種方式:jdk實現動態代理和cglib 動態代理實現。
1.jdk實現動態代理
package com.shuaiwen.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 製作代理的類
* @author acer
*
*/
public class JdkHandler implements InvocationHandler{
private Object target;
public JdkHandler(Object target) {
super();
this.target = target;
}
//獲取動態創建的代理角色
public Object getProxy(){
//返回運行期動態創建 的代理角色
/**
* 1.類加載器
* 2.目標對象實現的接口
* 3.實現了InvocationHandler實現類
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public void before(){
System.out.println("方法執行前 執行。。。");
}
public void after(){
System.out.println("方法執行後 執行。。。");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//增強目標對象的行爲
before();
Object result =null;
//執行目標對象的方法
result = method.invoke(target, args);
after();
return result;
}
}
測試類
package com.shuaiwen.test;
import com.shuaiwen.proxy.JdkHandler;
import com.shuaiwen.proxy.Marry;
import com.shuaiwen.proxy.You;
public class Test01 {
public static void main(String[] args) {
/**
* jdk代理對象中的真實角色必須實現相應的接口
*/
JdkHandler jdkHandler = new JdkHandler(new You());
Marry marry = (Marry) jdkHandler.getProxy();
marry.toMarry();
}
}
結果爲:
結婚前的佈置。。。
終於等到你,還好沒放棄。。
結婚後的感言。。。
注意點:jdk代理對象中的真實角色必須實現相應的接口,否則出錯。
2.cglib動態代理
code generator library ,操作字節碼。 與jdk提供的代理區別:
Proxy:委託類必須有接口,製作過程比較快,執行慢;
cglib:委託類可以沒有接口,繼承的思維來實現相似性,製作代理過程比較慢,執行快。主要解決沒有接口類的代理實現。
package com.shuaiwen.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* cglib創建動態代理
* @author acer
*
*/
public class CglibInterceptor implements MethodInterceptor{
private Object target;
public CglibInterceptor(Object target) {
this.target = target;
}
public Object getProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public void before(){
System.out.println("方法執行前 執行。。。");
}
public void after(){
System.out.println("方法執行後 執行。。。");
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
before();
Object result = null;
result = arg3.invoke(target, arg2);
after();
return result;
}
}
測試類和上面的結果類似。。