动态代理

代理模式需要为每个类编写一个代理类,动态代理则会自动生成代理类简化操作。
实现动态代理有两种方式java自带api和cglib。

java自带api

基于接口生成代理类,实现动态代理

/**
 * 功能接口
 */
public interface MyDao {
    void create();

    void query();

    void update();

    void delete();
}

/**
 * 功能类
 */
public class MyDaoImp implements MyDao {
    public void create() {
        // 第八步:正真的create方法被调用
        System.out.println("create something ... ");
    }

    public void query() {
        System.out.println("query something ... ");
    }

    public void update() {
        System.out.println("update something ... ");
    }

    public void delete() {
        System.out.println("delete something ... ");
    }
}

/**
 * 委托类
 */
public class Agent implements InvocationHandler {

    private Object proxied;
    private int id;

    public Agent(Object proxied, int id) {
        this.proxied = proxied;
        this.id = id;
    }

    // 通过代理类我们实现了权限过滤
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 第六步:目标方法调用前做一些业务操作,我们这里做了权限过滤
        if (method.getName().equals("query")) {
            return method.invoke(proxied, args);
        }

        if (id != 110) {
            System.out.println("id=" + id + "没有" + method.getName() + "权限");
            return null;  // 空对象
        }
        // 第七步:利用反射调用了MyDaoImp中的create方法
        return method.invoke(proxied, args);
    }
}

/**
 * 测试类
 */
public class Main {

    public static void main(String[] args) {
        // 第一步:新建对象,调用函数
        Main main = new Main();
        main.start();
        // main.getClassFile(new Class[]{MyDao.class});
    }

    private void start() {

        int id = 1101;
        // 第二步:新建委托类,传入被代理的功能类,以及我们业务需要的id
        Agent agent = new Agent(new MyDaoImp(), id);
        // 第三步:取得代理对象,传入类加载器、实现的接口数组、代理类,这时会根据传入的参数生成一个代理类$Proxy0
        MyDao myDao = (MyDao) Proxy.newProxyInstance(MyDaoImp.class.getClassLoader(), new Class[]{MyDao.class}, agent);
        // 第四步:调用create方法,由于我们使用的是接口,所以我们正真拿到的对象并不是MyDaoImp,而是第三步生成的实现了MyDao的$Proxy0类(以create方法为例讲解调用步骤)
        myDao.create();
        myDao.query();
        myDao.delete();
        myDao.update();

    }

    // 该方法可以获取动态生成的代理类
    private void getClassFile(Class[] classes) {
        byte[] classFile = ProxyGenerator.generateProxyClass("com.sun.proxy.$Proxy0", classes);

        FileOutputStream out = null;

        try {
            out = new FileOutputStream(("D:/$Proxy0.class"));
            out.write(classFile);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 生成的代理类
 * 可用测试类中的getClassFile方法取得class文件
 */
public final class $Proxy0 extends Proxy implements MyDao {
    private static Method m1;
    private static Method m6;
    private static Method m2;
    private static Method m4;
    private static Method m5;
    private static Method m0;
    private static Method m3;

    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 query() throws  {
        try {
            super.h.invoke(this, m6, (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 void delete() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void create() throws  {
        try {
            // 第五步:调用Agent中的invoke方法
            // super.h 在构造器中传入,即为Agent对象
            // m5 在静态块中加载,反射取得MyDao中的create方法
            super.h.invoke(this, m5, (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);
        }
    }

    public final void update() throws  {
        try {
            super.h.invoke(this, m3, (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", new Class[]{Class.forName("java.lang.Object")});
            m6 = Class.forName("core.proxy.jdk.MyDao").getMethod("query", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m4 = Class.forName("core.proxy.jdk.MyDao").getMethod("delete", new Class[0]);
            m5 = Class.forName("core.proxy.jdk.MyDao").getMethod("create", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m3 = Class.forName("core.proxy.jdk.MyDao").getMethod("update", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

注:

该动态代理的原理,根据传入的委托类和接口,利用java的字节码技术自动生成一个新的代理类。
由于我们使用的是接口,所用我们真正使用的是生成的代理类。
该动态代理有一个接口
spring默认使用该动态代理技术

cglib

基于继承生成代理类,实现动态代理

/**
 * 功能类
 */
public class MyDaoImp {
    public void create() {
        System.out.println("create something ... ");
    }

    public void query() {
        System.out.println("query something ... ");
    }

    public void update() {
        System.out.println("update something ... ");
    }

    public void delete() {
        System.out.println("delete something ... ");
    }
}

/**
 * 委托类
 */
 public class Agent implements MethodInterceptor {

    private int id;

    public Agent(int id) {
        this.id = id;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 第九步:处理业务员逻辑
        if (method.getName().equals("query")) {
            return methodProxy.invokeSuper(o, objects);
        }

        if (id != 110) {
            System.out.println("id=" + id + "没有" + method.getName() + "权限");
            return NoOp.INSTANCE;  // 空对象
        }
        // 第十步:调用真正的业务类
        return methodProxy.invokeSuper(o, objects);
    }
}

/**
 * 测试类
 */
public class Main {

    public static void main(String[] args) {
        // 第一步:新建对象,调用函数
        Main main = new Main();
        main.start();
    }

    public void start() {
        int id = 111;
        // 第二步:新建委托类
        Agent agent = new Agent(id);
        // 第三步:新建代理类处理对象
        Enhancer enhancer = new Enhancer();
        // 第四步:设置生成代理对象的父类
        enhancer.setSuperclass(MyDaoImp.class);
        // 第五步:设置委托类
        enhancer.setCallback(agent);
        // 第六步:取得生成的代理类,返回的类为MyDaoImp的子类
        MyDaoImp myDaoImp = (MyDaoImp) enhancer.create();
        // 第七步:调用create方法,实际调用了MyDaoImp子类的create方法,(以create方法为例继续接下去的流程)
        myDaoImp.create();
        myDaoImp.query();
        myDaoImp.update();
        myDaoImp.delete();
        getClassFile(enhancer);
    }

    // 获取代理对象字节码文件
    private void getClassFile(Enhancer enhancer){

        FileOutputStream out = null;

        try {
            byte[] bytes = DefaultGeneratorStrategy.INSTANCE.generate(enhancer);
            out = new FileOutputStream(("D:/Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72.class"));
            out.write(bytes);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 生成的代理类
 * 可用测试类中的getClassFile方法取得class文件
 */
public class aa28f65a extends core.proxy.cglib.MyDaoImp implements net.sf.cglib.proxy.Factory {
    private boolean CGLIB$BOUND;
    public static java.lang.Object CGLIB$FACTORY_DATA;
    private static final java.lang.ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final net.sf.cglib.proxy.Callback[] CGLIB$STATIC_CALLBACKS;
    private net.sf.cglib.proxy.MethodInterceptor CGLIB$CALLBACK_0;
    private static java.lang.Object CGLIB$CALLBACK_FILTER;
    private static final java.lang.reflect.Method CGLIB$update$0$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$update$0$Proxy;
    private static final java.lang.Object[] CGLIB$emptyArgs;
    private static final java.lang.reflect.Method CGLIB$delete$1$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$delete$1$Proxy;
    private static final java.lang.reflect.Method CGLIB$create$2$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$create$2$Proxy;
    private static final java.lang.reflect.Method CGLIB$query$3$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$query$3$Proxy;
    private static final java.lang.reflect.Method CGLIB$equals$4$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$equals$4$Proxy;
    private static final java.lang.reflect.Method CGLIB$toString$5$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$toString$5$Proxy;
    private static final java.lang.reflect.Method CGLIB$hashCode$6$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$hashCode$6$Proxy;
    private static final java.lang.reflect.Method CGLIB$clone$7$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$clone$7$Proxy;

    static void CGLIB$STATICHOOK2() { /* compiled code */ }

    final void CGLIB$update$0() { /* compiled code */ }

    public final void update() { /* compiled code */ }

    final void CGLIB$delete$1() { /* compiled code */ }

    public final void delete() { /* compiled code */ }

    final void CGLIB$create$2() { /* compiled code */ }

    // 生成的代理类无法完全反编译
    // 第八步:调用Agent的intercept方法
    // 预测无法反编译的内容为 intercept(this, CGLIB$create$2$Method, null, CGLIB$create$2$Proxy)
    public final void create() { /* compiled code */ }

    final void CGLIB$query$3() { /* compiled code */ }

    public final void query() { /* compiled code */ }

    final boolean CGLIB$equals$4(java.lang.Object o) { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    final java.lang.String CGLIB$toString$5() { /* compiled code */ }

    public final java.lang.String toString() { /* compiled code */ }

    final int CGLIB$hashCode$6() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    final java.lang.Object CGLIB$clone$7() throws java.lang.CloneNotSupportedException { /* compiled code */ }

    protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException { /* compiled code */ }

    public static net.sf.cglib.proxy.MethodProxy CGLIB$findMethodProxy(net.sf.cglib.core.Signature signature) { /* compiled code */ }

    public aa28f65a() { /* compiled code */ }

    public static void CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    public static void CGLIB$SET_STATIC_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    private static final void CGLIB$BIND_CALLBACKS(java.lang.Object o) { /* compiled code */ }

    public java.lang.Object newInstance(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    public java.lang.Object newInstance(net.sf.cglib.proxy.Callback callback) { /* compiled code */ }

    public java.lang.Object newInstance(java.lang.Class[] classes, java.lang.Object[] objects, net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    public net.sf.cglib.proxy.Callback getCallback(int i) { /* compiled code */ }

    public void setCallback(int i, net.sf.cglib.proxy.Callback callback) { /* compiled code */ }

    public net.sf.cglib.proxy.Callback[] getCallbacks() { /* compiled code */ }

    public void setCallbacks(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
}

注:

该动态代理的原理,根据传入的委托类和业务类,利用java的字节码技术自动生成一个新的代理类。
生成的代理类为被代理的子类。
spring可选择使用该动态代理技术

参考文章
已忘记。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值