【问题标题】:Spring4D Container Interception a-la Aspect Oriented Programming (AOP)Spring4D 容器拦截 a-la 面向方面编程 (AOP)
【发布时间】:2022-03-04 06:17:19
【问题描述】:

目标:

  • 在 Delphi 编程语言中。
  • 拦截所有虚方法的切面。
  • 其构造函数需要参数的类。
  • 一个依赖注入 (DI) 容器,两者
    • 创建类的一个实例,将正确的参数传递给构造函数。
    • 将方面应用于实例,以便拦截对实例上的虚拟方法的所有调用。

我已经尝试使用 Spring4D 容器和拦截抽象来做到这一点:

下面的代码什么也不输出。我想要类似的输出代码:

Intercepted one
Intercepted two
Intercepted three
unit Main;

interface

uses
  Spring.Container,
  Spring.Interception,
  Spring.Services;

procedure Run;

type
  TAspect = class(TInterfacedObject, IInterceptor)
  public
    procedure Intercept(const Invocation: IInvocation);
  end;
  TDependency = class(TObject)
    procedure two; virtual;
  end;
  TTarget = class(TObject)
    var FDependency: TDependency;
    constructor Create(const Dependency: TDependency);
    procedure one; virtual;
    procedure three; virtual;
  end;

implementation

procedure Run;
begin
  GlobalContainer.RegisterType<TAspect>;
  GlobalContainer.RegisterType<TDependency>.InterceptedBy<TAspect>;
  GlobalContainer.RegisterType<TTarget>.InterceptedBy<TAspect>;
  GlobalContainer.Build;
  var Target := ServiceLocator.GetService<TTarget>;
  Target.one;
end;

procedure TAspect.Intercept(const Invocation: IInvocation);
begin
  Writeln('Intecepted ' + Invocation.Method.Name);
  Invocation.Proceed;
end;

procedure TDependency.two;
begin
end;

constructor TTarget.Create(const Dependency: TDependency);
begin
  inherited Create;
  FDependency := Dependency;
end;

procedure TTarget.one;
begin
  FDependency.two;
  three;
end;

procedure TTarget.three;
begin
end;

end.

我尝试了类似的方法,它拦截了对虚拟方法的所有调用,但它不满足上面列出的所有目标,因为它不通过 DI 容器。

var Aspect: IInterceptor := TAspect.Create;
var Target := TProxyGenerator.CreateClassProxy<TTarget>([Aspect]);

我也尝试使用容器,但委托给调用 TProxyGenerator 的东西,并拦截对虚拟方法的所有调用,但它不能满足上面列出的所有目标,因为它只能使用零参数构造函数(即没有构造函数注入)。

【问题讨论】:

  • 你问的具体问题是什么?
  • 我如何实现列出的目标?

标签: delphi dependency-injection aop spring4d


【解决方案1】:

通过InterceptedBy 的拦截器只能由容器作为代理应用于基于接口的服务。这仅仅是因为 a)如何管理此类的生命周期没有歧义,并且 b)所有方法调用都通过代理,而不是基于类的服务,后者仅拦截虚拟方法。

当这被应用到上面的代码时,你会得到一和二的输出,但不是三的输出,因为该方法是从 TTarget 实例中调用的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多