什么是IOC和AOP?

打印 上一主题 下一主题

主题 978|帖子 978|积分 2934

什么是IOC?

IOC(Inversion of Control,控制反转) 是一种设计原则,广泛应用于软件设计中,特别是在面向对象编程(OOP)中。IOC的核心思想是将对象的创建和管理从应用程序的代码中分离出来,交给一个外部的容器或框架来处理。这种设计原则有助于提高代码的可维护性、可测试性和模块化程度。
IOC的主要形式:

  • 依赖注入(Dependency Injection,DI):


  • 依赖注入是一种实现IOC的具体方式,通过外部容器将对象的依赖关系注入到对象中,而不是对象本身创建或管理这些依赖。
  • 依赖注入可以分为构造函数注入、属性注入和方法注入。
    1.   public interface ILogger
    2.   {
    3.           void Log(string message);
    4.   }
    5.   public class ConsoleLogger : ILogger
    6.   {
    7.           public void Log(string message)
    8.           {
    9.                   Console.WriteLine(message);
    10.           }
    11.   }
    12.   public class UserService
    13.   {
    14.           private readonly ILogger _logger;
    15.           // 构造函数注入
    16.           public UserService(ILogger logger)
    17.           {
    18.                   _logger = logger;
    19.           }
    20.           public void RegisterUser(string name)
    21.           {
    22.                   _logger.Log($"Registering user: {name}");
    23.                   // 用户注册逻辑
    24.           }
    25.   }
    26.   // 使用依赖注入容器
    27.   public class Program
    28.   {
    29.           public static void Main()
    30.           {
    31.                   var serviceProvider = new ServiceCollection()
    32.                           .AddSingleton<ILogger, ConsoleLogger>()
    33.                           .AddTransient<UserService>()
    34.                           .BuildServiceProvider();
    35.                   var userService = serviceProvider.GetService<UserService>();
    36.                   userService.RegisterUser("John Doe");
    37.           }
    38.   }
    复制代码

  • 服务定位器(Service Locator):


  • 服务定位器是一种模式,应用程序通过一个全局的服务容器来获取所需的对象。
  • 这种方式使得对象的创建和管理更加会合,但可能会导致代码的耦合度增加。
    1.   public class ServiceLocator
    2.   {
    3.           private static readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
    4.           public static void Register<T>(T service)
    5.           {
    6.                   _services[typeof(T)] = service;
    7.           }
    8.           public static T Resolve<T>()
    9.           {
    10.                   return (T)_services[typeof(T)];
    11.           }
    12.   }
    13.   public class UserService
    14.   {
    15.           private readonly ILogger _logger;
    16.           public UserService()
    17.           {
    18.                   _logger = ServiceLocator.Resolve<ILogger>();
    19.           }
    20.           public void RegisterUser(string name)
    21.           {
    22.                   _logger.Log($"Registering user: {name}");
    23.                   // 用户注册逻辑
    24.           }
    25.   }
    26.   // 使用服务定位器
    27.   public class Program
    28.   {
    29.           public static void Main()
    30.           {
    31.                   ServiceLocator.Register<ILogger>(new ConsoleLogger());
    32.                   var userService = new UserService();
    33.                   userService.RegisterUser("John Doe");
    34.           }
    35.   }
    复制代码
IOC的长处

  • 降低耦合度:


  • IOC通过将对象的创建和管理交给外部容器,淘汰了对象之间的直接依赖关系,提高了代码的模块化程度。

  • 提高可维护性:


  • 由于依赖关系的管理被外部化,修改或替换某个组件的实现时,只需在容器中进行更改,而不必修改使用该组件的代码。

  • 增强可测试性:


  • IOC使得单位测试更加容易。可以通过注入模仿对象(Mock Objects)来测试组件,而不必依赖实际的实现。

  • 简化代码管理:


  • IOC容器负责创建和管理对象的生命周期,淘汰了应用程序代码中的样板代码(Boilerplate Code)。
IOC容器
许多当代的框架和库提供了IOC容器来支持依赖注入。以下是一些常用的IOC容器:

  • Microsoft.Extensions.DependencyInjection:


  • .NET Core 提供的内置依赖注入容器。
    1.   public class Startup
    2.   {
    3.           public void ConfigureServices(IServiceCollection services)
    4.           {
    5.                   services.AddSingleton<ILogger, ConsoleLogger>();
    6.                   services.AddTransient<UserService>();
    7.           }
    8.   }
    9.   public class Program
    10.   {
    11.           public static void Main(string[] args)
    12.           {
    13.                   var serviceProvider = new ServiceCollection()
    14.                           .AddSingleton<ILogger, ConsoleLogger>()
    15.                           .AddTransient<UserService>()
    16.                           .BuildServiceProvider();
    17.                   var userService = serviceProvider.GetService<UserService>();
    18.                   userService.RegisterUser("John Doe");
    19.           }
    20.   }
    复制代码

  • Unity:
    由微软开发的轻量级依赖注入容器。
    var container = new UnityContainer();
    container.RegisterType();
    container.RegisterType();
    var userService = container.Resolve();
    userService.RegisterUser("John Doe");
  • Autofac:
    一个功能强大的依赖注入容器。
    var builder = new ContainerBuilder();
    builder.RegisterType().As();
    builder.RegisterType();
    var container = builder.Build();
    var userService = container.Resolve();
    userService.RegisterUser("John Doe");
  • Ninject:
    另一个流行的依赖注入框架。
    1. var kernel = new StandardKernel();
    2. kernel.Bind<ILogger>().To<ConsoleLogger>();
    3. kernel.Bind<UserService>().ToSelf();
    4. var userService = kernel.Get<UserService>();
    5. userService.RegisterUser("John Doe");
    复制代码
总结
控制反转(IOC):是一种设计原则,将对象的创建和管理交给外部容器或框架来处理。
依赖注入(DI):是实现IOC的一种具体方式,通过外部容器将对象的依赖关系注入到对象中。
长处:

  • 降低耦合度
  • 提高可维护性
  • 增强可测试性
  • 简化代码管理
    IOC容器:许多框架和库提供了IOC容器来支持依赖注入,如Microsoft.Extensions.DependencyInjection、Unity、Autofac和Ninject。
================================
什么是AOP?
AOP(面向切面编程,Aspect-Oriented Programming) 是一种编程范式,旨在通过将横切关注点(Cross-Cutting Concerns)从主要业务逻辑中分离出来,提高代码的模块化和可维护性。横切关注点是指那些影响多个模块的功能,比方日志记录、事务管理、安全性检查、性能监控等。AOP通过在运行时动态地将这些关注点应用到代码中,使得开发者可以更专注于业务逻辑的实现,而不必重复编写横切逻辑。
AOP的核心概念

  • 切面(Aspect):


  • 切面是横切关注点的模块化表现。它包罗一些横切逻辑和用于指定这些逻辑何时应用的点。
  • 示例:日志记录、事务管理等可以定义为切面。

  • 毗连点(Join Point):


  • 毗连点是程序执行过程中的一个点,如方法的调用、异常的抛出等。
  • 在这些点上可以应用横切逻辑。

  • 切入点(Pointcut):


  • 切入点用于定义在哪些毗连点上应用横切逻辑。
  • 切入点通过匹配规则(如方法名、定名空间等)来指定。
  • 示例:在所有方法调用前记录日志的切入点可以定义为execution(* *(..))。

  • 通知(Advice):


  • 通知是实际执行的横切逻辑代码。
  • 通知可以在毗连点的特定位置执行,比方方法调用前、方法调用后、异常抛出时等。
  • 示例:日志记录使用可以在方法调用前执行(前置通知)。

  • 目标对象(Target Object):


  • 目标对象是被横切逻辑增强的对象。
  • AOP框架在运行时会动态地将横切逻辑应用到目标对象上。

  • 织入(Weaving):


  • 织入是将切面应用到目标对象的过程。
  • 织入可以在编译时(Compile-time Weaving)、类加载时(Load-time Weaving)或运行时(Runtime Weaving)进行。
AOP的实现方式
AOP可以通过不同的方式实现,具体取决于使用的框架和工具。常见的AOP实现方式包罗:

  • 编译时织入:


  • 在编译阶段将切面逻辑织入到目标对象的字节码中。
  • 示例:AspectJ在Java中的编译时织入。

  • 类加载时织入:


  • 在类加载阶段将切面逻辑织入到目标对象中。
  • 示例:某些Java AOP框架支持类加载时织入。

  • 运行时织入:


  • 在运行时动态地将切面逻辑应用到目标对象中。
  • 示例:Spring AOP(Java)和PostSharp(C#)支持运行时织入。
AOP在C#中的应用
在C#中,AOP通常通过第三方库来实现,其中最常见的是PostSharp和Castle DynamicProxy。以下是一些常见的AOP库及其特点:

  • PostSharp:


  • 一个强大的AOP框架,支持编译时和运行时织入。
  • 提供丰富的通知类型,如方法调用前、方法调用后、异常处理等。
    1.   using PostSharp.Aspects;
    2.   [Serializable]
    3.   public class LogAttribute : OnMethodBoundaryAspect
    4.   {
    5.           public override void OnEntry(MethodExecutionArgs args)
    6.           {
    7.                   Console.WriteLine($"Entering method: {args.Method.Name}");
    8.           }
    9.           public override void OnExit(MethodExecutionArgs args)
    10.           {
    11.                   Console.WriteLine($"Exiting method: {args.Method.Name}");
    12.           }
    13.   }
    14.   public class UserService
    15.   {
    16.           [Log]
    17.           public void RegisterUser(string name)
    18.           {
    19.                   Console.WriteLine($"Registering user: {name}");
    20.                   // 用户注册逻辑
    21.           }
    22.   }
    23.   public class Program
    24.   {
    25.           public static void Main()
    26.           {
    27.                   var userService = new UserService();
    28.                   userService.RegisterUser("John Doe");
    29.           }
    30.   }
    复制代码

  • Castle DynamicProxy:
一个动态代理库,可以在运行时创建代理对象,并在代理对象的方法调用前后插入横切逻辑。
  1.         using Castle.DynamicProxy;
  2.         public interface IUserService
  3.         {
  4.                 void RegisterUser(string name);
  5.         }
  6.         public class UserService : IUserService
  7.         {
  8.                 public void RegisterUser(string name)
  9.                 {
  10.                         Console.WriteLine($"Registering user: {name}");
  11.                         // 用户注册逻辑
  12.                 }
  13.         }
  14.         public class LoggingInterceptor : IInterceptor
  15.         {
  16.                 public void Intercept(IInvocation invocation)
  17.                 {
  18.                         Console.WriteLine($"Entering method: {invocation.Method.Name}");
  19.                         invocation.Proceed();
  20.                         Console.WriteLine($"Exiting method: {invocation.Method.Name}");
  21.                 }
  22.         }
  23.         public class Program
  24.         {
  25.                 public static void Main()
  26.                 {
  27.                         var proxyGenerator = new ProxyGenerator();
  28.                         var loggingInterceptor = new LoggingInterceptor();
  29.                         var userService = proxyGenerator.CreateInterfaceProxyWithTarget<IUserService>(new UserService(), loggingInterceptor);
  30.                         userService.RegisterUser("John Doe");
  31.                 }
  32.         }
复制代码
AOP的长处

  • 模块化:


  • AOP将横切关注点模块化,使得代码更加清晰和易于维护。
  • 不同的横切逻辑可以独立开发和测试。

  • 淘汰重复代码:


  • 通过AOP,可以制止在多个地方重复编写雷同的横切逻辑。

  • 提高可测试性:


  • AOP使得业务逻辑和横切逻辑分离,便于单位测试和集成测试。

  • 机动性:


  • AOP可以在不修改现有代码的情况下添加新的功能,提高了代码的机动性。
AOP的缺点

  • 学习曲线:


  • AOP引入了新的概念和工具,增加了学习和明白的难度。

  • 调试困难:


  • 由于横切逻辑是在运行时动态插入的,调试这些逻辑可能更加复杂。

  • 性能开销:


  • 动态代理和织入使用可能会引入一定的性能开销,特别是在高并发环境下。
总结
面向切面编程(AOP):是一种编程范式,通过将横切关注点从主要业务逻辑中分离出来,提高代码的模块化和可维护性。

  • 核心概念:

    • 切面(Aspect):横切关注点的模块化表现。
    • 毗连点(Join Point):程序执行过程中的特定点。
    • 切入点(Pointcut):定义在哪些毗连点上应用横切逻辑。
    • 通知(Advice):实际执行的横切逻辑代码。
    • 目标对象(Target Object):被横切逻辑增强的对象。
    • 织入(Weaving):将切面应用到目标对象的过程。

  • 实现方式:

    • 编译时织入
    • 类加载时织入
    • 运行时织入

  • 在C#中的应用:

    • PostSharp
    • Castle DynamicProxy

  • 长处:

    • 模块化
    • 淘汰重复代码
    • 提高可测试性
    • 机动性

  • 缺点:

    • 学习曲线
    • 调试困难
    • 性能开销
      通过使用AOP,开发者可以更专注于核心业务逻辑的实现,而不必担心横切逻辑的实现和管理。这有助于提高代码的质量和可维护性。

AOP介绍大纲

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

石小疯

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表