博客
关于我
十分钟理解Java之动态代理
阅读量:202 次
发布时间:2019-02-28

本文共 4775 字,大约阅读时间需要 15 分钟。

Java动态代理技术详解

代理的概念

在微商代理中,代理类代替厂家(委托类)销售商品,厂家对客户而言是不可见的。这种代理机制具有两个主要优势:

  • 隐藏委托类实现:代理类可以屏蔽委托类的具体实现,使得客户看不到背后的厂家。
  • 解耦客户与委托类:通过代理类可以对客户和委托类进行解耦,通常用于增加功能或对方法进行统一处理。
  • 静态代理

    静态代理是在程序运行前定义的代理类,代理类和委托类通常实现同一接口或继承自相同的父类。在Java中,常见的静态代理实现方式是通过引用持有委托类对象。

    例子

    public interface Sell {    void sell();    void ad();}public class Vendor implements Sell {    public void sell() {        System.out.println("In sell method");    }    public void ad() {        System.out.println("ad method");    }}public class BusinessAgent implements Sell {    private Vendor mVendor;    public BusinessAgent(Vendor vendor) {        mVendor = vendor;    }    public void sell() {        mVendor.sell();    }    public void ad() {        mVendor.ad();    }}

    通过BusinessAgent代理类,可以在不修改Vendor类代码的情况下增加过滤逻辑,比如只允许大学生购买商品。

    限制

    静态代理的缺点是需要预先定义代理类,且每个方法都需要手动处理逻辑,这在方法数量较多时效率低下。

    动态代理

    动态代理通过在运行时生成代理类,避免了手动编写大量代理代码。这种方式的优势在于可以对代理类的方法进行统一处理,而无需修改每个代理类的代码。

    动态代理的优势

    动态代理适用于需要对多个代理类方法进行统一处理的场景,例如:

    • 在方法执行前后添加日志记录
    • 实现方法的通用验证逻辑
    • 对不同代理类统一处理异常

    动态代理的实现

    动态代理基于InvocationHandler接口,代理类通过调用处理器拦截方法调用。

    InvocationHandler接口

    public interface InvocationHandler {    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}

    例子

    public class DynamicProxy implements InvocationHandler {    private Object obj;    public DynamicProxy(Object obj) {        this.obj = obj;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("before");        Object result = method.invoke(obj, args);        System.out.println("after");        return result;    }}

    动态生成代理类

    public class Main {    public static void main(String[] args) {        DynamicProxy inter = new DynamicProxy(new Vendor());        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");        Sell sell = (Sell) Proxy.newProxyInstance(            Sell.class.getClassLoader(),            new Class[]{Sell.class},            inter        );        sell.sell();        sell.ad();    }}

    代理类源码

    反编译后的代理类代码如下:

    package com.sun.proxy;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 Sell {    private static Method m1;    private static Method m2;    private static Method m4;    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})).booleanValue();        } 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 ad() 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 sell() throws {        try {            super.h.invoke(this, m3, (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")});            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);            m4 = Class.forName("Sell").getMethod("ad", new Class[0]);            m3 = Class.forName("Sell").getMethod("sell", 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());        }    }}

    总结

    动态代理通过在运行时生成代理类,解决了静态代理的局限性,提供了更高的灵活性和可维护性。通过InvocationHandler接口,可以对代理类方法的调用进行统一处理,适用于需要对多个代理类方法进行通用处理的场景。

    转载地址:http://duhs.baihongyu.com/

    你可能感兴趣的文章
    Netty相关
    查看>>
    Network Dissection:Quantifying Interpretability of Deep Visual Representations(深层视觉表征的量化解释)
    查看>>
    Network Sniffer and Connection Analyzer
    查看>>
    NetworkX系列教程(11)-graph和其他数据格式转换
    查看>>
    Networkx读取军械调查-ITN综合传输网络?/读取GML文件
    查看>>
    Net与Flex入门
    查看>>
    net包之IPConn
    查看>>
    NFinal学习笔记 02—NFinalBuild
    查看>>
    NFS共享文件系统搭建
    查看>>
    nfs复习
    查看>>
    NFS网络文件系统
    查看>>
    ng 指令的自定义、使用
    查看>>
    nginx + etcd 动态负载均衡实践(二)—— 组件安装
    查看>>
    nginx + etcd 动态负载均衡实践(四)—— 基于confd实现
    查看>>
    Nginx + Spring Boot 实现负载均衡
    查看>>
    Nginx + uWSGI + Flask + Vhost
    查看>>
    Nginx - Header详解
    查看>>
    Nginx Location配置总结
    查看>>
    Nginx upstream性能优化
    查看>>
    Nginx 中解决跨域问题
    查看>>