spring-aop前篇之代理模式-JDK动态代理

弥补静态代理会产生类爆炸的缺点,动态代理营运而生。JDK动态代理只能代理接口(因为动态代理生成的代理类已经继承了Proxy,所以只能代理接口)

实现JDK动态代理有哪些步骤呢

1,新建一个接口并新建其实现类(JDK动态代理中称之为目标对象即targetObject)

2,新建代理类实现InvocationHandler接口重写invoke方法

先上个简单的图,不喜勿喷

下面请看代码演示

public interface UserDao {

    void query(String id);

    void insert(int id,String name);
}

public class UserDaoImpl implements  UserDao {
    @Override
    public void query(String id) {
        System.out.println("query db --id:"+id);
    }

    @Override
    public void insert(int id, String name) {
        System.out.println("insert db --id:"+id+"--name:"+name);
    }
}


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

public class UserDaoProxy implements InvocationHandler {

    UserDao target;//目标对象UserDaoImpl

    public UserDaoProxy(UserDao target){
        this.target = target;
    }


    public Object getInstance(){//通过Proxy对象 根据 目标对象 创建其 代理对象
        Object object = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        return  object;
    }

    //proxy 代理对象 即 $Proxy0 
    //targetMethod 目标对象的query,insert方法 
    //targetArgs 目标对象的参数 [110] , [1,222]
    @Override
    public Object invoke(Object proxy, Method targetMethod, Object[] targetArgs) throws Throwable {
        sout("aop before......")
        return targetMethod.invoke(target,targetArgs);
        sout("aop after......")
    }
}


public class Test {
    public static void main(String[] args) {
        //目标对象
        UserDao target = new UserDaoImpl();
        //代理类对象
        UserDaoProxy proxyClass = new UserDaoProxy(target);
        //代理对象
        UserDao Proxy =(UserDao) proxyClass.getInstance();

        Proxy.query("110");
        Proxy.insert(1,"222");
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    }
}

实现InvocationHandler接口 debug调试程序(非源码)

这儿有2个对象,分别是target 目标对象 即 UserDaoImpl

proxyClass 代理类对象 产生代理对象 和 代理执行目标对象的方法

下面进去看第三个对象代理对象 这个代理对象应该是 $Proxy 开头的

这边的三个对象

第一个是当前类的类对象即代理类对象就是上图的那个proxyClass = UserDaoProxy@626

第二个对象object={$Proxy0@657}  这个对象就是回返的代理对象 $Proxy 开头的

第三个对象是代理对象target 就是上图的target = UserDaoImpl@623的

继续回来看返回的代理对象 就是那个$Proxy 开头的

System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

通过这行代码可以看到底层帮我们创建的代理对象$Proxy0,可以知道为什么只能代理接口了,因为Java语法限制理想情况下只能单继承

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

package com.sun.proxy;

import com.dao.UserDao;
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 UserDao {
    private static Method m1;
    private static Method m4;
    private static Method m2;
    private static Method m3;
    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});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void query(String var1) throws  {
        try {
            super.h.invoke(this, m4, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    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 void insert(int var1, String var2) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

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

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m4 = Class.forName("com.dao.UserDao").getMethod("query", Class.forName("java.lang.String"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.dao.UserDao").getMethod("insert", Integer.TYPE, Class.forName("java.lang.String"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

我们下面看下jdk动态代理底层是如何帮我们实现的

本周五更新

猜你喜欢

转载自blog.csdn.net/qq_38108719/article/details/100003709