天天看點

Java設計模式-代理模式定義優缺點實作

最近學習到設計模式,現總結個人學習代理模式内容【更加關注過程,對被代理對象完全控制】。

上一篇:Java設計模式-委派模式

文章目錄

  • 定義
  • 優缺點
    • 優點
    • 缺點
  • 實作
    • CGLIB代理
      • 代碼
      • 測試
    • JDK代理
      • 代碼
      • 測試
    • 對比

定義

為其他對象提供一種代理以控制對這個對象的通路。在某些情況下,一個對象不适合或者不能直接引用另一個對象,而代理對象可以在用戶端和目标對象之間起到中介的作用

優缺點

優點

  • (1).職責清晰,不用關心其他非本職責的事務。
  • (2).代理對象可以在用戶端和目标對象之間起到中介的作用,這樣起到了中介的作用和保護了目标對象的作用。
  • (3).高擴充性 [1]

缺點

  • 需要重新建立不可見對象。達到重寫的目的。
  • 使用到了反射,降低了性能。

實作

CGLIB代理

代碼

代理對象需要實作MethodInterceptor,屬于cglib.jar包。

cglib内部建立一個對象,繼承我們的對象[LoginWorkflow ],在建立的對象上重寫了父類的方法,但是還是會使用父類的邏輯,而代理代碼,則在業務邏輯前後添加其他業務邏輯。

Java設計模式-代理模式定義優缺點實作
/**
 * 登入流程
 * @author cc百川
 */
public class LoginWorkflow {
	public String doSubmit(){
		System.out.println("正在登入");
		return "登入成功";
	}
}
public class ProxyLog implements MethodInterceptor{
	public Object install(Class clazz) throws Exception{
		Enhancer enhancer = new Enhancer();
		//告訴cglib,生成的子類需要繼承哪個父類
		enhancer.setSuperclass(clazz);
		enhancer.setCallback(this);//設定回調,告訴繼續執行業務代碼的類
		
		//生成源代碼,編譯成class檔案,加載到JVM中,并傳回被代理對象
		return enhancer.create();//建立被代理對象
	}
	@Override
	public Object intercept(Object obj, Method arg1, Object[] arg2,
			MethodProxy proxy) throws Throwable {
		System.out.println("代理登入前處理業務邏輯,判斷是否規定時間登入");
		//該obj的引用是由CGLib給我們new出來的,這個是被代理對象的子類,子類引用強轉父類,這時就可以操作父類的屬性 
		String res = (String) proxy.invokeSuper(obj, arg2);
		System.out.println("代理登入後處理日志相關等");
		return res+",代理添加了日志";
	}
}
           

測試

Java設計模式-代理模式定義優缺點實作

JDK代理

代碼

jdk代理核心實作InvocationHandler。

jdk代理需要借助接口,也就是被代理者實作一個接口【這裡是Workflow】。

jdk實作代理過程

  • 1.拿到被代理對象的引用,然後擷取它的接口
  • 2.JDK代理重新生成一個類,同時實作我們給的代理對象所實作的接口
  • 3.把被代理對象的引用也拿到了
  • 4.重新動态生成一個class位元組碼
  • 5.然後編譯
    Java設計模式-代理模式定義優缺點實作
/**
 * 流程送出
 * @author cc百川
 */
public interface Workflow {
	String doSubmit();
}

/**
 * 登入流程
 * @author cc百川
 */
public class LoginWorkflow implements Workflow{
	public String doSubmit(){
		System.out.println("正在登入");
		return "登入成功";
	}
}

/**
 * 代理登入 jdk代理核心實作InvocationHandler
 * @author cc百川
 */
public class ProxyLog implements InvocationHandler{
	//用于保留被代理對象的引用
	private Workflow wf;
	
	//擷取被代理的對象【資料】
	public Object install(Workflow wf) {
		this.wf = wf;
		Class cs = wf.getClass();
		return Proxy.newProxyInstance(cs.getClassLoader(), cs.getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("代理登入前處理業務邏輯,判斷是否規定時間登入");
		String res = (String) method.invoke(this.wf, args);//執行原業務邏輯
		System.out.println("代理登入後處理日志相關等");
		return res+",代理添加了日志";
	}
}
           

測試

通過代理的方式,可以在執行業務代碼前後添加邏輯

Java設計模式-代理模式定義優缺點實作

對比

JDK的動态代理是通過接口來進行強制轉換的,生成以後的代理對象,可以強制轉換為接口。

CGLib的動态代理是通過生成一個被代理對象的子類,然後重寫父類的方法。子類引用強轉給父類【被代理類】,進而調用對象方法。

日常對代理模式,常見有AOP,以及産品二開等,達到無侵入修改【後期舉例】。

以上僅為個人學習,如果錯誤望指出,謝謝。

繼續閱讀