Dynamic Proxy

本文通过示例详细解析了Java动态代理的实现原理,展示了如何利用ProxyGenerator生成代理类,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于Dynamic Proxy的原理,很多地方都有介绍,里面最神秘的就是JVM会在运行时动态生成一个类,好奇心驱使,想看看这个生成的类的代码是啥样的。于是,跟踪到Proxy.newProxyInstance()中,发现生成代码的关键语句byte[] ProxyGenerator.generateProxyClass(String proxyname,Class[] instances),写了段代码来输出那个类文件,并得到反编译的结果
----------IPerson .java-----------
package cn.edu.tju.bme;

public interface IPerson {

   public void insertPerson();
    public String getPersonName();
}
----------TestInvocationHandler.java-----------
package cn.edu.tju.bme;

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

public class TestInvocationHandler implements InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // TODO Auto-generated method stub
        return null;
    }
}
------------Main.java-----------
package cn.edu;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;

import sun.misc.ProxyGenerator;

import cn.edu.tju.bme.IPerson;
import cn.edu.tju.bme.TestInvocationHandler;

public class Main {
    public static void main(String[] args) throws IOException {
        String proxyName = "proxyName";
        InvocationHandler handler = new TestInvocationHandler();
        byte[] proxyClassFile =    ProxyGenerator.generateProxyClass(  proxyName, new Class[]{IPerson.class});
        FileOutputStream fos = new FileOutputStream(new File("D://ProxyName.class"));
        fos.write(proxyClassFile);
        fos.flush();
        fos.close();
    }
}
---------------------------
反编译生成的ProxyName.class,得到的源文件如下:
----------proxyName.java-----------
import cn.edu.tju.bme.IPerson;
import java.lang.reflect.*;

public final class proxyName extends Proxy
    implements IPerson
{

    public proxyName(InvocationHandler invocationhandler)
    {
        super(invocationhandler);
    }

    public final String toString()
    {
        try
        {
            return (String)super.h.invoke(this, m2, null);
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final int hashCode()
    {
        try
        {
            return ((Integer)super.h.invoke(this, m0, null)).intValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final String getPersonName ()
    {
        try
        {
            return (String)super.h.invoke(this, m4, null);
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final void insertPerson ()
    {
        try
        {
            super.h.invoke(this, m3, null);
            return;
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final boolean equals(Object obj)
    {
        try
        {
            return ((Boolean)super.h.invoke(this, m1, new Object[] {
                obj
            })).booleanValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    private static Method m2;
    private static Method m0;
    private static Method m4;
    private static Method m3;
    private static Method m1;

    static
    {
        try
        {
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m4 = Class.forName("cn.edu.tju.bme.IPerson").getMethod("getPersonName", new Class[0]);
            m3 = Class.forName("cn.edu.tju.bme.IPerson").getMethod("insertPerson", new Class[0]);
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
                Class.forName("java.lang.Object")
            });
        }
        catch(NoSuchMethodException nosuchmethodexception)
        {
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());
        }
内容概要:本文详细探讨了杯形谐波减速器的齿廓修形方法及寿命预测分析。文章首先介绍了针对柔轮与波发生器装配时出现的啮合干涉问题,提出了一种柔轮齿廓修形方法。通过有限元法装配仿真确定修形量,并对修形后的柔轮进行装配和运转有限元分析。基于Miner线性疲劳理论,使用Fe-safe软件预测柔轮寿命。结果显示,修形后柔轮装配最大应力从962.2 MPa降至532.7 MPa,负载运转应力为609.9 MPa,解决了啮合干涉问题,柔轮寿命循环次数达到4.28×10⁶次。此外,文中还提供了详细的Python代码实现及ANSYS APDL脚本,用于柔轮变形分析、齿廓修形设计、有限元验证和疲劳寿命预测。 适合人群:机械工程领域的研究人员、工程师,尤其是从事精密传动系统设计和分析的专业人士。 使用场景及目标:①解决杯形谐波减速器中柔轮与波发生器装配时的啮合干涉问题;②通过优化齿廓修形提高柔轮的力学性能和使用寿命;③利用有限元分析和疲劳寿命预测技术评估修形效果,确保设计方案的可靠性和可行性。 阅读建议:本文涉及大量有限元分析和疲劳寿命预测的具体实现细节,建议读者具备一定的机械工程基础知识和有限元分析经验。同时,读者可以通过提供的Python代码和ANSYS APDL脚本进行实际操作和验证,加深对修形方法和技术路线的理解。
### DynamicProxy 的简介 DynamicProxy 是由 Castle Project 提供的一个强大的动态代理库,用于在运行时生成代理对象并拦截方法调用。它广泛应用于 AOP(面向切面编程)、日志记录、性能监控以及事务管理等领域。 通过 `Castle.DynamicProxy` 库,开发者可以轻松实现对目标类或接口的方法调用进行拦截和扩展功能[^1]。 --- ### 动态代理的核心概念 #### 1. **代理生成** 动态代理允许在不修改原始代码的情况下,为目标对象创建一个代理实例。这个代理可以在方法执行前后插入自定义逻辑。 例如: ```csharp var proxy = new ProxyGenerator() .CreateClassProxy<MyClass>(new Interceptor()); proxy.Flag = true; proxy.Execute(); ``` 上述代码展示了如何使用 `ProxyGenerator` 创建一个针对 `MyClass` 类型的代理,并传入了一个名为 `Interceptor` 的拦截器[^1]。 #### 2. **拦截器机制** 拦截器是一个实现了 `IInterceptor` 接口的对象,负责捕获被代理方法的调用过程。以下是典型的拦截器实现方式: ```csharp public class MyInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine($"Before calling {invocation.Method.Name}"); // 调用实际的目标方法 invocation.Proceed(); Console.WriteLine($"After calling {invocation.Method.Name}"); } } ``` 当某个方法被调用时,拦截器会先执行其内部逻辑(如打印日志),再通过 `invocation.Proceed()` 执行原生方法[^3]。 --- ### 配合 Autofac 使用 `Autofac.Extras.DynamicProxy` 是基于 `Castle.DynamicProxy` 构建的一个扩展包,旨在简化依赖注入框架中的动态代理集成。以下是如何配置 Autofac 来支持动态代理的功能: #### 注册拦截器 首先注册拦截器到容器中: ```csharp builder.RegisterType<UnitOfWorkIInterceptor>(); ``` #### 对服务启用拦截 接着为特定的服务类型启用拦截功能: ```csharp builder.RegisterAssemblyTypes(assemblies) .Where(t => typeof(IAppService).IsAssignableFrom(t) && !t.IsAbstract) .AsImplementedInterfaces() .InstancePerLifetimeScope() .InterceptedBy(typeof(UnitOfWorkIInterceptor)) .EnableInterfaceInterceptors(); ``` 此段代码表示:对于所有继承了 `IAppService` 并非抽象类型的类,都会自动应用 `UnitOfWorkIInterceptor` 拦截器[^3]。 --- ### 异步方法的支持 `Castle.DynamicProxy` 支持拦截异步方法,但需要注意一些细节。例如,如果要拦截返回 `Task<T>` 的方法,则应在拦截器中正确处理任务完成状态。下面是一段示例代码展示如何安全地拦截异步操作: ```csharp public async Task InterceptAsyncMethod(IInvocation invocation) { try { await (Task)invocation.Method.Invoke(invocation.Proxy, invocation.Arguments); } catch (Exception ex) { Console.WriteLine($"Error occurred: {ex.Message}"); throw; } } ``` 注意这里直接调用了反射来触发异步方法的实际执行流程[^3]。 --- ### 总结 `Castle.DynamicProxy` 提供了一种灵活的方式来增强现有业务逻辑而无需侵入原有代码结构。无论是简单的属性访问还是复杂的跨线程场景下的异常捕捉,都可以借助该工具箱达成目的。同时配合像 Autofac 这样的 DI 容器能够进一步提升开发效率与维护便利性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值