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();

simple_proxy.png

这种代理模式也最为简单,就是通过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();

于是你的代理模型会变成这样:

dynamic_proxy.png

毫无疑问,仅仅为了扩展同样的功能,在方案一种,我们会重复创建多个逻辑相同,仅仅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

原文地址:https://www.cnblogs.com/erma0-007/p/8653214.html