Java 静态代理

Posted 小黑妹007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 静态代理的主要内容,如果未能解决你的问题,请参考以下文章

Java动态代理

Java动态代理

Java动态代理

Java 静态代理

Java 静态代理和动态代理

java静态代理与动态代理简单分析