08-动态代理

本文详细介绍了Java中的JDK动态代理和CGLIB代理技术,包括如何在接口被代理的目标对象为final的情况下创建代理,以及MethodProxy的工作原理,展示了如何通过代理机制增强目标对象的行为。
摘要由CSDN通过智能技术生成

JDK

被代理的目标对象

interface Foo {
    void foo();
}

/**
 * jdk代理中  被代理的目标对象可以是final的
 */
static final class Target implements Foo {

    @Override
    public void foo() {
        System.out.println("Target.foo");
    }

}

生成代理对象

// 被代理的目标对象
Foo target = new Target();
/**
 * JDK代理只能针对接口类型
 * proxyFoo是动态生成的对象
 * 代理对象与目标对象都实现了接口类 是同级的兄弟关系
 */
Foo proxyFoo = (Foo) Proxy.newProxyInstance(JDKProxyDemo.class.getClassLoader(), 
                                            new Class[]{Foo.class}, 
                                            new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before.....");
                Object invokeRet = method.invoke(target, args);
                System.out.println("after.....");
                return invokeRet;
            }
});

proxyFoo.foo();

模拟JDK动态代理代码

被代理的目标对象

interface Foo {
    void foo();

    int bar();
}

/**
 * jdk代理中  被代理的目标对象可以是final的
 */
static final class Target implements Foo {

    @Override
    public void foo() {
        System.out.println("Target.foo");
    }

    @Override
    public int bar() {
        System.out.println("Target.bar");
        return 100;
    }
}

模拟动态代理代码

public class $Proxy0 extends Proxy implements JDKProxyDemo0.Foo {

    public $Proxy0(InvocationHandler h) {
        super(h);
    }

    static Method foo;
    static Method bar;

    static {
        try {
            foo = JDKProxyDemo0.Foo.class.getMethod("foo");
            bar = JDKProxyDemo0.Foo.class.getMethod("bar");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }

    @Override
    public void foo() {
        try {
            h.invoke(this, foo, new Object[0]);
        } catch (RuntimeException | Error e) {
            throw e;
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public int bar() {
        try {
            return (int) h.invoke(this, bar, new Object[0]);
        } catch (RuntimeException | Error e) {
            throw e;
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}

测试

$Proxy0 $Proxy0 = new $Proxy0((proxy, method, args1) -> {
    System.out.println("before");
    Object invokeRet = method.invoke(new Target(), args);
    System.out.println("after");
    return invokeRet;
});

$Proxy0.foo();
$Proxy0.bar();

CGLIB

被代理的目标对象

/**
 * cglib代理中  被代理的目标对象不可以是final的  方法也不能是final的
 * 因为代理对象是通过继承Target类实现的
 */
static class Target {
    public void foo() {
        System.out.println("Target.foo");
    }
}

生成代理对象

//Target target = new Target();

/**
 * 代理对象继承了目标对象  是父子关系
 */
Target proxy = (Target) Enhancer.create(Target.class, new MethodInterceptor() {
    @Override
    public Object intercept(Object proxy, Method targetMethod, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("before...");
        // 反射实现调用目标方法  效率不高
        //Object invokeRet = targetMethod.invoke(target, args);

        // 内部没有使用反射    但是需要有目标对象  spring选择了此方式
        // Object invokeRet = methodProxy.invoke(target, args);

        // 内部没有使用反射  且不需要有目标对象
        Object invokeRet = methodProxy.invokeSuper(proxy, args);

        System.out.println("after...");
        return invokeRet;
    }
});

proxy.foo();

模拟CGLIB动态代理代码

被代理的目标对象

public class Target {

    public void save() {
        System.out.println("Target.save()");
    }

    public void save(int i) {
        System.out.println("Target.save i(" + i + ")");
    }

    public void save(long i) {
        System.out.println("Target.save l(" + i + ")");

    }
}

代理对象

public class Proxy extends Target {

    @Setter
    private MethodInterceptor methodInterceptor;

    static Method save;
    static Method savei;
    static Method savel;

    static MethodProxy saveMethodProxy;
    static MethodProxy saveiMethodProxy;
    static MethodProxy savelMethodProxy;

    static {
        try {
            save = Target.class.getMethod("save");
            savei = Target.class.getMethod("save", int.class);
            savel = Target.class.getMethod("save", long.class);

            saveMethodProxy = MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
            saveiMethodProxy = MethodProxy.create(Target.class, Proxy.class, "(I)V", "save", "saveSuper");
            savelMethodProxy = MethodProxy.create(Target.class, Proxy.class, "(J)V", "save", "saveSuper");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }

    // ==================> 原始功能方法
    public void saveSuper() {
        super.save();
    }

    public void saveSuper(int i) {
        super.save(i);
    }

    public void saveSuper(long i) {
        super.save(i);
    }

    // ==================> 带有增强功能的方法
    @Override
    public void save() {
        try {
            methodInterceptor.intercept(this, save, new Object[0], saveMethodProxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(int i) {
        try {
            methodInterceptor.intercept(this, savei, new Object[]{i}, saveiMethodProxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(long i) {
        try {
            methodInterceptor.intercept(this, savel, new Object[]{i}, savelMethodProxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}

测试

Target target = new Target();

Proxy proxy = new Proxy();
proxy.setMethodInterceptor(new MethodInterceptor() {
    @Override
    public Object intercept(Object proxy, Method targetMethod, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("before...");
        // 反射执行
        //Object invokeRet = targetMethod.invoke(target, args);

        // 无反射  需要目标对象
        //Object invokeRet = methodProxy.invoke(target, args);

        // 无反射  需要代理对象
        Object invokeRet = methodProxy.invokeSuper(proxy, args);
        System.out.println("after...");
        return invokeRet;
    }
});

proxy.save();
proxy.save(1);
proxy.save(2L);

MethodProxy是如何避免反射的???

被代理的目标对象FastClass

public class TargetFastClass /*extends FastClass*/ {

    static Signature s0 = new Signature("save", "()V");
    static Signature s1 = new Signature("save", "(I)V");
    static Signature s2 = new Signature("save", "(J)V");

    /**
     * 定义【目标对象】方法的序号  并根据签名返回对应的序号
     *
     * @param signature
     * @return
     */
    public int getIndex(Signature signature) {
        if (s0.equals(signature)) {
            return 0;
        } else if (s1.equals(signature)) {
            return 1;
        } else if (s2.equals(signature)) {
            return 2;
        }
        // 未找到
        return -1;
    }

    /**
     * 根据方法编号  正常调用方法(非反射  但需要目标对象自己调用)
     *
     * @param index
     * @param target 目标对象
     * @param args
     * @return
     */
    public Object invoke(int index, Object target, Object[] args) {
        if (index == 0) {
            ((Target) target).save();
            return null;
        } else if (index == 1) {
            ((Target) target).save((int) args[0]);
            return null;
        } else if (index == 2) {
            ((Target) target).save(((long) args[0]));
            return null;
        }
        throw new RuntimeException("无此方法");
    }

    public static void main(String[] args) {
        Target target = new Target();
        // MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
        TargetFastClass fastClass = new TargetFastClass();
        int index = fastClass.getIndex(new Signature("save", "()V"));
        // Object invokeRet = methodProxy.invoke(target, args);
        fastClass.invoke(index, target, new Object[0]);

        index = fastClass.getIndex(new Signature("save", "(I)V"));
        fastClass.invoke(index, target, new Object[]{1});

        index = fastClass.getIndex(new Signature("save", "(J)V"));
        fastClass.invoke(index, target, new Object[]{2L});

    }


}

代理对象的FastClass

public class ProxyFastClass /*extends FastClass*/ {

    static Signature s0 = new Signature("saveSuper", "()V");
    static Signature s1 = new Signature("saveSuper", "(I)V");
    static Signature s2 = new Signature("saveSuper", "(J)V");

    /**
     * 定义【代理对象】方法的序号  并根据签名返回对应的序号
     *
     * @param signature
     * @return
     */
    public int getIndex(Signature signature) {
        if (s0.equals(signature)) {
            return 0;
        } else if (s1.equals(signature)) {
            return 1;
        } else if (s2.equals(signature)) {
            return 2;
        }
        // 未找到
        return -1;
    }

    /**
     * 根据方法编号  正常调用方法(非反射  但需要代理对象自己调用)
     *
     * @param index
     * @param proxy 代理对象
     * @param args
     * @return
     */
    public Object invoke(int index, Object proxy, Object[] args) {
        if (index == 0) {
            ((Proxy) proxy).saveSuper();
            return null;
        } else if (index == 1) {
            ((Proxy) proxy).saveSuper((int) args[0]);
            return null;
        } else if (index == 2) {
            ((Proxy) proxy).saveSuper(((long) args[0]));
            return null;
        }
        throw new RuntimeException("无此方法");
    }

    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        // MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
        ProxyFastClass fastClass = new ProxyFastClass();
        int index = fastClass.getIndex(new Signature("saveSuper", "()V"));
        // Object invokeRet = methodProxy.invokeSuper(proxy, args);
        fastClass.invoke(index, proxy, new Object[0]);

        index = fastClass.getIndex(new Signature("saveSuper", "(I)V"));
        fastClass.invoke(index, proxy, new Object[]{1});

        index = fastClass.getIndex(new Signature("saveSuper", "(J)V"));
        fastClass.invoke(index, proxy, new Object[]{2L});

    }


}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

层巅余落日

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值