Java静态代理与动态代理

1.代理

代理类相比于目标类,多做了一些工作,可以看做是对目标类的增强。

2.静态代理

代理类和目标类实现同一个接口,然后在创建代理对象时,通过构造器塞入一个目标对象。在代理对象的方法中调用目标对象的方法,在调用目标方法的前后可以执行自定义的方法,实现对目标对象方法的增强。

优点:在编译器实现代理,性能更好。

缺点:需要手动为每一个目标类编写对应的代理类,代码规模增加太快。

3.动态代理

代理类通过java.lang.reflect.Proxy获取代理对象;实现java.lang.reflect.InvocationHandler接口,在invoke() 方法中实现对目标对象方法的增强。

优点:只需要写一个代理类,就可以代理不同的目标类。

缺点:运行期实现代理,性能也比静态代理更差一点。

 

例:

接口:

public interface MathInterface {
    int getSum(int... nums);
}

 目标类:

public class MathInterfaceImpl implements MathInterface {
    @Override
    public int getSum(int... nums) {
        int sum = 0;
        StringBuilder sb = new StringBuilder();
        for (int i : nums) {
            sum += i;
            sb.append(i).append("+");
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
            sb.append("=").append(sum);
        }
        System.out.println(sb.toString());
        return sum;
    }
}

静态代理类:

import java.util.Arrays;

public class StaticProxy implements MathInterface {
    private MathInterface proxy;

    StaticProxy(MathInterface proxy) {
        this.proxy = proxy;
    }

    @Override
    public int getSum(int... nums) {
        System.out.println("静态代理类前置打印:\n入参:" + Arrays.toString(nums));
        int sum = proxy.getSum(nums);
        System.out.println("静态代理类后置打印:\n运算结果:" + sum);
        return sum;
    }
}

动态代理类:

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

public class DynamicProxy implements InvocationHandler {
    private Object proxy;
    private ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public Object getInstance(Object proxy) {
        this.proxy = proxy;
        return Proxy.newProxyInstance(this.proxy.getClass().getClassLoader(), this.proxy.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        if (beforeInvoke(proxy, method, args)) {
            result = method.invoke(this.proxy, args);
        }
        afterInvoke(proxy, method, args, result);
        return result;
    }

    private boolean beforeInvoke(Object proxy, Method method, Object[] args) {
        if (method == null) {
            return false;
        }
        long startTime = System.currentTimeMillis();
        threadLocal.set(startTime);
        System.out.println("动态代理前置打印:\n方法:" + method + "\t开始执行时间:" + startTime + "\t线程:" + Thread.currentThread().getName());
        return true;
    }

    private void afterInvoke(Object proxy, Method method, Object[] args, Object result) {
        System.out.println("动态代理类后置打印:\n结果:" + result.toString() + "\t耗时:" + (System.currentTimeMillis() - threadLocal.get()) + "ms" + "\t线程:" + Thread.currentThread().getName());
        // 这需要手动remove,不然会有内存泄露问题
        threadLocal.remove();
    }
}

测试类:

public class ProxyDemo {
    public static void main(String[] args) throws Exception {
        // 静态代理
        MathInterfaceImpl impl = new MathInterfaceImpl();
        MathInterface obj = new StaticProxy(impl);
        obj.getSum(1, 2, 3, 45, 25, 2);


        System.out.println("\n\n\n\n");
        // 动态代理
        DynamicProxy proxy = new DynamicProxy();
        MathInterface sub = (MathInterface) proxy.getInstance(new MathInterfaceImpl());
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    sub.getSum(1, 23, 62, 85, 28, 525, 5);
                }
            }).start();
        }
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值