0

在工作中与同事进行了讨论:我们很困惑 AOP 是否与 DI 有点相似,因为代理对象开始发挥作用@AOP,并阅读(下文)Spring DI 也使用动态代理来创建对象

http://www.postsharp.net/blog/post/Anders-Hejlsberg-Dead-Body.aspx

现在所有的依赖注入框架都带有一些类似 AOP 的特性:当你需要一个接口的实现时,你不会收到实现本身,而是会收到一个代理(称为 DynamicProxy),这个代理在调用最终实施。It looks like AOP, it smells like AOP,但它很难与成熟的 AOP 框架相提并论。

4

3 回答 3

3

我想说的是,使用依赖注入使基于动态代理的 AOP 更易于使用,因此是一条自然的路径。

但是你可以在不使用 AOP 的情况下使用依赖注入,也可以在不使用依赖注入的情况下使用 AOP。顺便说一句,代理不仅用于实现 AOP,还用于解决循环依赖关系或能够将较小范围的对象(例如,请求范围的对象)注入到较大范围的对象(例如,单例范围的对象)中。

于 2013-03-24T17:07:24.523 回答
1
  • 依赖注入是将组件注入到需要其行为的组件中。
  • 面向方面的编程是关于将横切关注点应用于代码(实际上是关于坚持开放/封闭原则)。

使用 DI 时,AOP 会变得更加自然。您可以使用代理来做到这一点,但我个人的偏好是通过应用好的旧装饰器来做到这一点。

它看起来像 AOP,闻起来像 AOP,但很难与成熟的 AOP 框架相提并论。

我完全不同意这篇声明的作者。根据我的经验,PostSharp 之类的工具可以让您解决应用程序中的设计缺陷。在处理遗留应用程序或无法更改的设计(例如处理INotityPropertyChanged接口)时,这可以使这些工具非常强大。然而,虽然这些工具允许您在不修复设计的情况下添加 AOP 功能,但这些设计缺陷仍然会在项目的整个生命周期中困扰您。

一个简单的例子是可测试性。像这样的工具并没有解决应用程序的可测试性问题,而依赖注入模式确实解决了这个问题。由于这些工具在编译时编织切面,这使得在没有切面的情况下测试代码非常困难(这是您在进行单元测试时需要做的事情,有时甚至在集成测试时也是如此)。您将不得不使用编译器指令做一些巧妙的技巧,但这只能解决部分问题,因为您仍然想测试这些方面,但只是孤立地测试,就像您想孤立地测试每段代码一样(这就是单元测试是关于)。即使你能解决它,你的代码仍然很难维护。无法维护的代码是由设计缺陷引起的。

文章的作者说:

第一个问题是动态代理仅允许您将方面添加到服务的显式边界,您选择公开为接口的那些。即使您愿意,也不能向私有或静态方法添加方面。

他对此完全正确,但是如果您想为私有或静态方法添加方面,那么您的设计就有问题:修复设计!

第二个问题更具戏剧性。当您沉迷于 AOP 的一些好处时,即使您不需要依赖注入,您也开始使用动态代理,仅仅因为动态代理的要求而改变代码的体系结构。这是错误的。AOP 不需要您更改代码的体系结构。

再一次,作者是对的:使用 PostSharp 时,您不需要更改 AOP 的体系结构。但是如果设计不正确,应用方面仍然要困难得多,即使使用 PostSharp 之类的工具也是如此。并且不要忘记使用 PostSharp 的无属性 AOP 只有在使用商业版本时才有可能。使用属性应用 AOP 仍然会导致高耦合和维护问题。所有 DI 工具(至少对于 .NET)都可以免费使用,并且默认使用无属性。

好的设计根本没有其他选择,当拥有像 PostSharp 这样的正确设计工具在大多数情况下变得多余时。它们在某些边缘情况下仍然是有益的(并且在这些情况下可能非常有益),但根据我的经验,当您的设计是SOLID时,这些情况很少见。

现在问题显然变成了:什么是好的 SOLID 设计?根本没有现成的、始终有效的设计可以应用于所有应用程序。我设计的每个应用程序都是不同的,尽管在过去几年中我看到了某些可能对您也有益的重复模式。我过去在这里这里这里都写过这个。这些文章中描述的模式已经成为我帮助设计和构建的许多应用程序的基本构建块。这些模式的关键成分是 SOLID。

于 2013-03-24T18:06:02.163 回答
1

不:

1) 依赖注入工具(控制反转容器)通常带有AOP/拦截工具(例如Castle Windsor 带有Castle DynamicProxy),但这是一种方便——IoC 工具不需要具有此功能。

2)无需依赖注入即可使用AOP工具。例如,无论您使用什么 IoC 工具,PostSharp 都可以独立工作。另一个例子:您可以在没有 IoC 容器的情况下使用 Castle DynamicProxy,但我无法想象您想要的许多场景。

(很抱歉在我的回答中使用了 .NET 工具,因为我对 Java 工具不太熟悉)。

于 2013-03-25T13:53:07.153 回答