Java——静态代理、动态代理

 https://blog.csdn.net/giserstone/article/details/17199755

代理的作用:业务类只需要关注业务逻辑本身,保证了业务类的重用性

一 静态代理

特点:

  程序运行前就已经存在代理类的字节码文件了,代理类和委托类的关系也在程序运行前就确定了 

实现:

  代理类继承了被代理类的接口;代理类将被代理类以成员变量的方式引入,在构造函数中初始化被代理类;共同接口中,引用成员变量的方法并在该接口中增加新功能以实现代理类的功能。

缺点:

  1)代理对象的一个接口只能服务于一种被代理对象,每有一种代理对象,就要多一个代理方法。

  2)代理类在程序一开始就要被加载,增加了内存负担

  3)如果接口类增加了一个方法,除了被代理对象要增加这个接口,代理对象也要增加这个接口,增加了程序维护的复杂度

  4)只能代理已知的对象

二 动态代理

特点:

  动态代理的字节码是在程序运行期间由JVM根据反射机制动态生成的,不存在代理类的字节码文件,代理类和委托类的关系是在程序运行时确定的

实现:

  1)实现InvocationHandler接口创建自己的调用处理器
  2)给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类
  3)以调用处理器类型为参数,利用反射机制得到动态代理类的构造函数
  4) 以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象

demo:

接口:

package com.test.aoptest.proxyTest;

public interface MyTask {
    void doing();

    void writing();
}

委托类:

 

package com.test.aoptest.proxyTest;

public class MyTaskImpl implements MyTask {
    @Override
    public void doing() {
        System.out.println("doing sth ...");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void writing() {
        System.out.println("writing sth ...");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

调度器:

package com.test.aoptest.proxyTest;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyTaskInvocationHandler implements InvocationHandler {

    private Object delegate;

    public MyTaskInvocationHandler(Object delegate) {
        this.delegate = delegate;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = method.invoke(delegate, args);
        long end = System.currentTimeMillis();
        System.out.println("执行任务耗时"+(end - start)+"毫秒");
        return result;
    }
}

主入口:

package com.test.aoptest.proxyTest;

import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {

        MyTaskImpl myTask = new MyTaskImpl();
        MyTask proxy = (MyTask) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                new Class[]{MyTask.class}, new MyTaskInvocationHandler(myTask));
        proxy.doing();
        proxy.writing();
//        System.out.println(proxy.hashCode());
//        System.out.println(myTask.hashCode());
//        System.out.println(myTask.equals(proxy));
//        System.out.println(myTask.toString());
//        System.out.println(proxy.toString());
    }
}

 System.identityHashCode(Object) 返回对象的内存地址,不管该对象的类是否重写了hashCode()方法。

posted @ 2019-07-30 14:10  高圈圈  阅读(161)  评论(0编辑  收藏  举报