江西雄基建设网站,海外网文,安徽省港航建设投资集团网站,重庆做网站的公司有哪些首先#xff0c;我们需要定义一个接口#xff0c;代表我们要代理的目标对象的功能#xff1a;
// 日志记录器接口
public interface ILogger
{/// summary/// 记录日志/// /summary/// param namemessage日志消息/paramvoid L…首先我们需要定义一个接口代表我们要代理的目标对象的功能
// 日志记录器接口
public interface ILogger
{/// summary/// 记录日志/// /summary/// param namemessage日志消息/paramvoid Log(string message);
}// 日志记录器实现类
public class Logger : ILogger
{public void Log(string message){Console.WriteLine($Logging: {message});}
}
然后我们创建一个代理类实现该接口并在目标方法的执行前后注入额外的逻辑
// 切面接口
public interface IInterceptor
{/// summary/// 在方法执行前执行的逻辑/// /summary/// param nametargetType目标类型/param/// param namemethodName方法名称/paramvoid BeforeMethod(Type targetType, string methodName);/// summary/// 在方法执行后执行的逻辑/// /summary/// param nametargetType目标类型/param/// param namemethodName方法名称/paramvoid 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
{/// summary/// 创建代理对象/// /summary/// typeparam nameTInterface目标接口类型/typeparam/// param nametarget目标对象实例/param/// param nameinterceptor切面对象实例/param/// returns代理对象/returnspublic static TInterface CreateProxyTInterface(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指令来生成和修改类型的字节码实现动态代理。这种方式相对于代理类的生成更加底层需要对CLRCommon 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。