Dynamic Proxy

本文探讨了Java中动态代理接口实现时的限制条件,包括接口必须为接口类型、不能重复实现相同接口、所有接口必须可见且来自同一包、接口方法不能冲突以及代理类接口数量不能超过VM限制。

 

http://www.javaworld.com/javaworld/jw-11-2000/jw-1110-proxy.html

 

  • Interestingly, you can have a proxy class that implements multiple interfaces. However, there are a few restrictions on the interfaces you implement. It is important to keep those restrictions in mind when creating your dynamic proxy:
  1. The proxy interface must be an interface. In other words, it cannot be a class (or an abstract class) or a primitive.
  2. The array of interfaces passed to the proxy constructor must not contain duplicates of the same interface. Sun specifies that, and it makes sense that you wouldn't be trying to implement the same interface twice at the same time. For example, an array { IPerson.class, IPerson.class } would be illegal, but the code { IPerson.class, IEmployee.class } would not. The code calling the constructor should check for that case and filter out duplicates.
  3. All the interfaces must be visible to the ClassLoader specified during the construction call. Again, that makes sense. The ClassLoadermust be able to load the interfaces for the proxy.
  4. All the nonpublic interfaces must be from the same package. You cannot have a private interface from package com.xyz and the proxy class in package com.abc. If you think about it, it is the same way when programming a regular Java class. You couldn't implement a nonpublic interface from another package with a regular class either.
  5. The proxy interfaces cannot have a conflict of methods. You can't have two methods that take the same parameters but return different types. For example, the methods public void foo() and public String foo() cannot be defined in the same class because they have the same signature, but return different types (see The Java Language Specification). Again, that is the same for a regular class.
  6. The resulting proxy class cannot exceed the limits of the VM, such as the limitation on the number of interfaces that can be implemented.


 

### 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 容器能够进一步提升开发效率与维护便利性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值