依赖注入有点类似于AOP吗?

时间:2013-03-24 16:50:22

标签: java dependency-injection proxy spring-aop

与同事讨论工作:如果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框架相比。

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

  • 依赖注入是指将组件注入需要其行为的组件中。
  • 面向方面编程是关于将横切关注点应用于代码(实际上是关于遵守Open/Closed Principle)。

使用DI时,AOP会更自然。您可以使用代理执行此操作,但我个人的偏好是通过应用良好的旧decorators来执行此操作。

  

它看起来像AOP,它闻起来像AOP,但它几乎不比a   完善的AOP框架。

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

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

文章的作者说:

  

第一个问题是动态代理只允许您添加方面   到服务的明确边界,你选择公开的那些   作为一个界面。您无法向私有或静态方法添加方面,   即使你想要。

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

  

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

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

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

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

答案 2 :(得分:1)

没有

1)依赖注入工具(控制容器的反转)通常带有 AOP /拦截工具(例如,Castle Windsor随Castle DynamicProxy一起提供),但这是方便的 - 它不是必需的使IoC工具具有此功能。

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

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