抽象主题接口:

public interface Subject {

    void doSomething();
}

真实主题类:

public class RealSubject implements Subject {

    public void doSomething() {
        System.out.println("RealSubject do something");
    }
}

代理者:

public class SubjectProxy implements Subject {

    private RealSubject realSubject = null;

    @Override
    public void doSomething() {

        beforeDoSomething();
        if(realSubject == null){
            realSubject =  new RealSubject();
        }
        realSubject.doSomething();
        afterDoSomething();

    }

    private void beforeDoSomething() {
        System.out.println("before doing something");
    }

    private void afterDoSomething() {
        System.out.println("after doing something");
    }

}

调用者:

public class Client {

    public static void main(String[] args) {

        Subject subject = (Subject) new SubjectProxy();//使用SubjectProxy代替Subject
        subject.doSomething();  //代理者代替真实者做事情
    }
}

 

静态代理的局限性

可以看到,静态代理让调用者不用再直接持有操作者的引用,而是将一切操作交由代理者去完成。但是静态代理也有它的局限性:

  1. 如果需要增加一个需要代理的方法,代理者的代码也必须改动进而适配新的操作;

  2. 如果需要代理者代理另外一个操作者,同样需要对代理者进行扩展并且更加麻烦。

可能有人想到可以用策略模式和工厂模式分别解决上面两个问题,但是,有没有更加巧妙的方法呢?首先,我们了解一下 Java 代码的执行过程。

理解 Java 代码执行流程

要从根本上理解动态代理的实现原理,得先从 Java 代码的执行流程说起:

1236742-5fa3251412b170d6.jpg

JVM 在运行 .class 文件之前,首先通过 ClassLoader 将 .class 文件以二进制的形式解析并生成实例以供调用,我们的代码执行逻辑是在 JVM 的运行期系统中进行工作的,那么,我们可不可以在自己的代码里面按照 .class 的格式生成自己的 .class 文件,进而调用自定义的 ClassLoader 将其加载出来呢?答案是肯定的,这样我们就可以动态地创建一个类了。

111.png