java动态代理之jdk的动态代理

Spring AOP的拦截功能是由java中的动态代理来实现的。java动态代理主要分为两种:一种是jdk的动态代理,一种是CGLIB动态代理。

两种动态代理的区别
jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借用第三方CGLIB库来实现的。
jdk动态代理是通过java的反射机制生成了一个继承proxy类的代理类,因为java中不允许多继承,所以被代理的只能是接口,jdk的动态代理生成的代理类会实现这个接口(下文会通过代码更直观的展示这个问题);而对于类的动态代理则需使用CGLIB来实现。

下面主要通过具体的案例详细的解释jdk动态代理的过程。首先定义一个接口和实现。

public interface ProxyInterface {
    public void printContent();
}
public class ProxyInterfaceImpl implements ProxyInterface {

    public void printContent() {
        System.out.println("I'm the target object's method!");
    }
}

JDK的动态代理主要用到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,我们需要通过实现该接口定义,然后通过反射机制调用目标类的方法。

public class MyInvokeHandler implements InvocationHandler {

    public Object target;//目标对象

    public MyInvokeHandler(Object target) {
        this.target = target;
    }

    /**
     * 执行目标对象的方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("------------------before------------------");

        // 执行目标对象的方法
        Object result = method.invoke(target, args);
        System.out.println("-------------------after------------------");

        return result;
    }


    /**
     * 获取目标对象的代理对象
     * @return 代理对象
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

public class MyProxyDemo {

    public static void main(String[] args) {
//该行代码是为了在本地生成代理文件    
 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); 
        ProxyInterface proxyInterface = new ProxyInterfaceImpl();
        System.out.println(proxyInterface.getClass());
        MyInvokeHandler handler = new MyInvokeHandler(proxyInterface);
        ProxyInterface proxy =  (ProxyInterface)handler.getProxy();
        System.out.println(proxy.getClass());
        proxy.printContent();

    }

}

打印结果:

class com.ll.interfacesImpl.ProxyInterfaceImpl
class com.sun.proxy.$Proxy0
------------------before------------------
I'm the target object's method!
-------------------after------------------

生成的代理类如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.ll.interfaces.ProxyInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements ProxyInterface {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void printContent() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m3 = Class.forName("com.ll.interfaces.ProxyInterface").getMethod("printContent", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值