Java 靜態代理
Java 靜態代理
靜態代理通常用於對原有業務邏輯的擴充。比如持有二方包的某個類,並調用了其中的某些方法。然後出於某種原因,比如記錄日誌、打印方法執行時間,但是又不好將這些邏輯寫入二方包的方法裏。所以可以創建一個代理類實現和二方方法相同的方法,通過讓代理類持有真實對象,然後在原代碼中調用代理類方法,來達到添加我們需要業務邏輯的目的。
這其實也就是代理模式的一種實現,通過對真實對象的封裝,來實現擴展性。
一個典型的代理模式通常有三個角色,這裏稱之為**代理三要素**
package singleton;
public class TestProxy {
public static void main(String[] args) {
Subject subject = new ProxySubject();
subject.request();
}
}
抽象角色
abstract class Subject {
public abstract void request();
}
真實角色
class RealSubject extends Subject {
@Override
public void request() {
System.out.println("From real subject");
}
}
代理角色
class ProxySubject extends Subject {
private RealSubject realSubject;// 代理角色內部引用了真是角色
@Override
public void request() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject) {
realSubject = new RealSubject();
}
realSubject.request();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作
}
private void preRequest() {
System.out.println("pre request");
}
private void postRequest() {
System.out.println("post request");
}
}
運行結果:
pre request
From real subject
post request
也可以用接口表示抽象角色
共同接口
public interface Action {
public void doSomething();
}
真實對象
public class RealObject implements Action{
public void doSomething() {
System.out.println("do something");
}
}
代理對象
public class Proxy implements Action {
private Action realObject;
public Proxy(Action realObject) {
this.realObject = realObject;
}
public void doSomething() {
System.out.println("proxy do");
realObject.doSomething();
}
}
運行代碼
Proxy proxy = new Proxy(new RealObject());
proxy.doSomething();
這種代理模式也最為簡單,就是通過proxy持有realObject的引用,並進行一層封裝。
靜態代理的優點和缺點
先看看代理模式的優點: 擴展原功能,不侵入原代碼。
再看看這種代理模式的缺點:
假如有這樣一個需求,有十個不同的RealObject,同時我們要去代理的方法是不同的,比要代理方法:doSomething、doAnotherThing、doTwoAnotherThing,添加代理前,原代碼可能是這樣的:
realObject.doSomething();
realObject1.doAnotherThing();
realObject2.doTwoAnother();
為了解決這個問題,我們有方案一:
為這些方法創建不同的代理類,代理後的代碼是這樣的:
proxy.doSomething();
proxy1.doAnotherThing();
proxy2.doTwoAnother();
當然,也有方案二:
通過創建一個proxy,持有不同的realObject,實現Action1、Action2、Action3接口,來讓代碼變成這樣:
proxy.doSomething();
proxy.doAnotherThing();
proxy.doTwoAnother();
於是你的代理模型會變成這樣:
毫無疑問,僅僅為了擴展同樣的功能,在方案一種,我們會重復創建多個邏輯相同,僅僅RealObject引用不同的Proxy。
而在方案二中,會導致proxy的膨脹,而且這種膨脹往往是無意義的。此外,假如方法簽名是相同的,更需要在調用的時候引入額外的判斷邏輯。
package Test;
public class TestProxy {
public static void main(String[] args) {
Action1 action1 = new ProxySubject();
action1.requestFirstThing();
Action2 action2 = new ProxySubject();
action2.requestSecondThing();
Action3 action3 = new ProxySubject();
action3.requestThirdThing();
}
}
interface Action1 {
void requestFirstThing();
}
interface Action2 {
void requestSecondThing();
}
interface Action3 {
void requestThirdThing();
}
class RealSubject1 implements Action1 {
@Override
public void requestFirstThing() {
System.out.println("From real subject1");
}
}
class RealSubject2 implements Action2 {
@Override
public void requestSecondThing() {
System.out.println("From real subject2");
}
}
class RealSubject3 implements Action3 {
@Override
public void requestThirdThing() {
System.out.println("From real subject3");
}
}
class ProxySubject implements Action1, Action2, Action3 {
private RealSubject1 realSubject1;// 代理角色內部引用了真是角色
private RealSubject2 realSubject2;// 代理角色內部引用了真是角色
private RealSubject3 realSubject3;// 代理角色內部引用了真是角色
@Override
public void requestFirstThing() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject1) {
realSubject1 = new RealSubject1();
}
realSubject1.requestFirstThing();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作
}
private void preRequest() {
System.out.println("pre request");
}
private void postRequest() {
System.out.println("post request");
}
@Override
public void requestThirdThing() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject2) {
realSubject2 = new RealSubject2();
}
realSubject2.requestSecondThing();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作
}
@Override
public void requestSecondThing() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject3) {
realSubject3 = new RealSubject3();
}
realSubject3.requestThirdThing();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作
}
}
運行結果:
pre request
From real subject1
post request
pre request
From real subject3
post request
pre request
From real subject2
post request
Java 靜態代理