java 代理

作者: const27 分类: All,开发-JAVA 发布时间: 2020-12-17 11:14

代理的作用,就是在原有类的代码不发生改动的情况下,添加新功能。起到一个修饰器的作用。

假设我们现在有个类,用于打印helloworld

class hello{
    public void gogo(){System.out.println("Hello Wrold");}
}

我们想在不改动hello类的前提下,在输出helloworld时同时输出当前时间到文件,达到日志的功能,该如何解决这个问题呢?以这个问题为切入点,开始学习代理。

静态代理

静态代理很简单,不用接触什么新技术。就是创建一个”继承已有的一个类
“的类,通过重写父类的方法,达到不改动原有类的基础上增添新功能。纸上得来终觉浅,用代码来说明一下吧。

以刚刚的输出helloworld的类为例。我们编写一个它的子类,并在其中重写其gogo方法,添加日志生成功能

class hello{
    public void gogo(){System.out.println("Hello Wrold");}
}

class static_hello_proxy extends hello{
    hello hello_obj;
    static_hello_proxy(hello hello){
        this.hello_obj = hello;
    }

    @Override
    public void gogo(){
        log();
        hello_obj.gogo();
    }

    public void log(){
        Date date = new Date();
        String value = "date:"+date+"\n";
        FileWriter writer = null;
        try {
            writer = new FileWriter(new File("log.txt"),true);
            writer.write(value);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}

然后主函数中我们只需调用static_hello_proxy中的gogo()方法就能达到日志功能了。这就是静态代理。
静态代理的缺点显而易见,如果我们想要代理不同的类,就要写出不同的静态代理类出来,同时我们也可能会遇到需要多个代理类来增添实现一个类的不同功能,有需要定义一大堆类出来。不容易维护,所以动态代理就诞生了,它很好的解决了静态代理会产生大量代理类的难题。

动态代理

使用动态代理,可以不用创建代理类,非常的方便。

动态代理由Proxy.newProxyInstance方法实现。

我们看看它的三个参数。
loader,顾名思义,就是被代理类的类加载器。
interfaces 被代理类所实现的接口,可通过 类对象.getinterfaces()获得
h 即 InvocationHandler接口类 的实现类,用于实现代理增添的方法

我们看看这个 InvocationHandler 类的结构。这个类只有一个invoke方法,且这个类是接口类。这个invoke方法就用于存放我们的增添的功能。

proxy即代理对象,method即对象中的某个方法,args即方法中的参数。

ok,接下来把刚刚那个类动态代理一下吧。但是需要注意的是动态代理只能代理接口实现类。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;

public class test {
    public static void main(String[] args){
        hello hello_obj = new hello();
        ClassLoader Loader = hello_obj.getClass().getClassLoader();
        Class<?>[] Interfaces = hello_obj.getClass().getInterfaces();
        InvocationHandler ih = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(method.getName()=="gogo"){
                    FileWriter writer = new FileWriter("log.txt");
                    writer.write("date:"+new Date()+"|by 动态代理\n");
                    writer.flush();
                    hello_obj.gogo();
                }
                return null;
            }
        };
        hello_interface proxy = (hello_interface) Proxy.newProxyInstance(Loader,Interfaces,ih);  //注意这里数据类型是接口的数据类型
        proxy.gogo();
    }
}

interface hello_interface{
    public void gogo();
}

class hello implements hello_interface{
    public void gogo(){System.out.println("Hello Wrold");}
}

OK,ALL DOWN

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

17 + 8 =

标签云