首先,我们需要定义一个接口,代表我们要代理的目标对象的功能:
- // 日志记录器接口
- public interface ILogger
- {
- ///
- /// 记录日志
- ///
- /// 日志消息
- void Log(string message);
- }
-
- // 日志记录器实现类
- public class Logger : ILogger
- {
- public void Log(string message)
- {
- Console.WriteLine($"Logging: {message}");
- }
- }
然后,我们创建一个代理类,实现该接口,并在目标方法的执行前后注入额外的逻辑:
- // 切面接口
- public interface IInterceptor
- {
- ///
- /// 在方法执行前执行的逻辑
- ///
- /// 目标类型
- /// 方法名称
- void BeforeMethod(Type targetType, string methodName);
-
- ///
- /// 在方法执行后执行的逻辑
- ///
- /// 目标类型
- /// 方法名称
- void AfterMethod(Type targetType, string methodName);
- }
-
- // 日志记录切面类
- public class LoggingAspect : IInterceptor
- {
- public void BeforeMethod(Type targetType, string methodName)
- {
- Console.WriteLine($"Before {targetType.Name}.{methodName}");
- }
-
- public void AfterMethod(Type targetType, string methodName)
- {
- Console.WriteLine($"After {targetType.Name}.{methodName}");
- }
- }
接下来,我们通过使用IL生成代理类型的字节码,动态创建代理对象:
- // 代理生成器
- public static class ProxyGenerator
- {
- ///
- /// 创建代理对象
- ///
- ///
目标接口类型 - /// 目标对象实例
- /// 切面对象实例
- ///
代理对象 - public static TInterface CreateProxy<TInterface>(TInterface target, IInterceptor interceptor)
- where TInterface : class
- {
- Type targetType = typeof(TInterface);
- TypeBuilder typeBuilder = CreateTypeBuilder(targetType);
- ImplementInterface(typeBuilder, targetType);
- ImplementMethods(typeBuilder, targetType, interceptor);
- Type proxyType = typeBuilder.CreateType();
- return Activator.CreateInstance(proxyType, target, interceptor) as TInterface;
- }
-
- private static TypeBuilder CreateTypeBuilder(Type targetType)
- {
- string typeName = targetType.Name + "Proxy";
- AssemblyName assemblyName = new AssemblyName(typeName);
- AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(typeName + "Module");
- TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class);
- typeBuilder.AddInterfaceImplementation(targetType);
- return typeBuilder;
- }
-
- private static void ImplementInterface(TypeBuilder typeBuilder, Type targetType)
- {
- foreach (MethodInfo method in targetType.GetMethods())
- {
- Type[] parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
- MethodBuilder methodBuilder = typeBuilder.DefineMethod(
- method.Name,
- MethodAttributes.Public | MethodAttributes.Virtual,
- method.ReturnType,
- parameterTypes
- );
- typeBuilder.DefineMethodOverride(methodBuilder, method);
- }
- }
-
- private static void ImplementMethods(TypeBuilder typeBuilder, Type targetType, IInterceptor interceptor)
- {
- foreach (MethodInfo method in targetType.GetMethods())
- {
- MethodBuilder methodBuilder = typeBuilder.GetMethod(method.Name).GetBaseDefinition() as MethodBuilder;
- if (methodBuilder != null)
- {
- ILGenerator ilGenerator = methodBuilder.GetILGenerator();
-
- // 调用切面方法
- ilGenerator.Emit(OpCodes.Ldarg_0); // 加载this到堆栈
- ilGenerator.Emit(OpCodes.Ldfld, typeBuilder.GetField("interceptor")); // 加载interceptor到堆栈
- ilGenerator.Emit(OpCodes.Ldarg_0); // 加载this到堆栈
- ilGenerator.Emit(OpCodes.Ldtoken, targetType); // 加载targetType到堆栈
- ilGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); // 调用GetTypeFromHandle方法
- ilGenerator.Emit(OpCodes.Ldstr, method.Name); // 加载方法名到堆栈
- ilGenerator.Emit(OpCodes.Callvirt, typeof(IInterceptor).GetMethod("BeforeMethod")); // 调用BeforeMethod方法
- ilGenerator.Emit(OpCodes.Pop); // 丢弃返回值
-
- // 调用目标方法
- ilGenerator.Emit(OpCodes.Ldarg_0); // 加载this到堆栈
- for (int i = 1; i <= method.GetParameters().Length; i++)
- {
- ilGenerator.Emit(OpCodes.Ldarg_S, i); // 加载方法参数到堆栈
- }
- ilGenerator.Emit(OpCodes.Callvirt, targetType.GetMethod(method.Name)); // 调用目标方法
-
- // 调用切面方法
- ilGenerator.Emit(OpCodes.Ldarg_0); // 加载this到堆栈
- ilGenerator.Emit(OpCodes.Ldfld, typeBuilder.GetField("interceptor")); // 加载interceptor到堆栈
- ilGenerator.Emit(OpCodes.Ldarg_0); // 加载this到堆栈
- ilGenerator.Emit(OpCodes.Ldtoken, targetType); // 加载targetType到堆栈
- ilGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); // 调用GetTypeFromHandle方法
- ilGenerator.Emit(OpCodes.Ldstr, method.Name); // 加载方法名到堆栈
- ilGenerator.Emit(OpCodes.Callvirt, typeof(IInterceptor).GetMethod("AfterMethod")); // 调用AfterMethod方法
- ilGenerator.Emit(OpCodes.Pop); // 丢弃返回值
- }
- }
- }
- }
最后,我们可以使用以下代码来测试动态代理的功能:
- class Program
- {
- static void Main(string[] args)
- {
- // 创建目标对象
- ILogger logger = new Logger();
-
- // 创建切面对象
- IInterceptor interceptor = new LoggingAspect();
-
- // 创建代理对象
- ILogger proxy = ProxyGenerator.CreateProxy(logger, interceptor);
-
- // 调用代理对象的方法
- proxy.Log("Hello, World!");
-
- Console.ReadLine();
- }
- }
对比一下Java Spring Boot 的AOP
动态代理实现方式:在Java Spring Boot中,基于代理的AOP主要使用JDK动态代理和CGLIB代理来实现。而在C#中,使用IL生成器(ILGenerator)直接操作IL指令来生成和修改类型的字节码,实现动态代理。这种方式相对于代理类的生成更加底层,需要对CLR(Common Language Runtime)和IL指令有一定的了解。
IL的语法和特性:IL是.NET平台的中间语言,类似于汇编语言,但具有一些.NET特定的语法和特性。IL指令用于描述类型、方法、属性等的结构和操作,需要了解这些指令的使用规则和约束。相比之下,Java字节码(Java bytecode)是Java虚拟机(JVM)上的中间语言,其语法和特性与IL有所不同。
第三方库和框架:在Java生态系统中,有许多第三方库和框架(如AspectJ、Spring AOP)提供了高级别的API和工具,使AOP的使用更加方便。而在C#中,虽然也有一些库(如Castle DynamicProxy、Unity Interception)可以辅助实现AOP,但相对于Java生态系统来说,可选择的工具和框架较少
综上所述,C#使用IL实现AOP与Java Spring Boot的AOP在实现方式、编程语言和生态系统等方面存在一些不同。C#开发者需要直接操作IL指令来生成和修改类型的字节码,需要对CLR和IL指令有一定的了解。而Java Spring Boot的AOP则基于代理实现,使用注解和切点表达式等高级别的API来配置和管理AOP。