学习笔记-静态&动态代理-基础复习

283 阅读2分钟

代理主要为代理对象提供一个真实对象的引用,由代理对象控制真实对象的行为,调用者不直接持有真实对象,有代理对象负责调度,类似中介模式。
(1)通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性;
(2)通过代理对象对访问进行控制;

静态代理

静态代理:一般是定义一个接口类或者抽象类,分别有真实对象和代理对象实现
接口类:

public interface Message {
    void message();
}

真实对象:

public class TextMessage implements Message{
    @Override
    public void message() {
        System.out.println("this is text!");
    }
}

代理对象:

public class MessProxy implements Message{
    private Message message = new TextMessage();
    @Override
    public void sayHello() {
        System.out.println("is before invoke" );
        message.message();
        System.out.println("is after invoke");
    }
}

直接调用代理对象即可

MessProxy messProxy = new MessProxy();
messProxy.message();

问题:
静态代理,一对一则会出现时静态代理对象量多、代码量大,从而导致代码复杂,可维护性差的问题,一对多则代 理对象会出现扩展能力差的问题。

动态代理

在运行时再创建代理类和其实例,因此显然效率更低。要完成这个场景,需要在运行期动态创建一个Class。JDK提 供了 Proxy 来完成这件事情。基本使用如下:

//抽象角色 
interface Api { 
    void test(String a); 
}
//真实角色 
class ApiImpl{ 
    @Override public void test(String a) {
        System.out.println("真实实现:" + a); 
    } 
}
//创建真实角色实例 
ApiImpl api = new ApiImpl(); 
//JDK动态代理: 
Proxy.newProxyInstance(getClass().getClassLoader(), 
            new Class[]{Api.class}, //JDK实现只能代理接口 
            new InvocationHandler() {
                @Override 
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
                    //执行真实对象方法 、
                    return method.invoke(api, args); 
                } 
            })

实际上, Proxy.newProxyInstance 会创建一个 Class,与静态代理不同,这个 Class 不是由具体的.java源文件编译 而来,即没有真正的文件,只是在内存中按照 Class 格式生成了一个 Class

String name = Api.class.getName()+"$Proxy0"; 
//生成代理指定接口的Class数据 
byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{Api.class}); 
FileOutputStream fos = new FileOutputStream("lib/" + name+".class"); 
fos.write(bytes); fos.close();

在初始化的时候得到所有的方法,在调用方法时,先会调用到生成的代理类的方法,然后通过 我们传入的 InvocationHandler 对象调用 对应的方法,将调用回调出来。