用AspectJ和Spring进行依赖项插入
来源:网络 更新时间:2014-12-2
依赖项插入和面向方面编程是互补的技术,所以想把它们结合在一起使用是很自然的。请跟随AdrianColyer一起探索两者之间的关系,并了解怎样才能把它们组合在一起,来促进高级的依赖项插入场景。
依赖项插入和面向方面编程(AOP)是两个关键的技术,有助于在企业应用程序中简化和纯化域模型和应用程序分层。依赖项插入封装了资源和协调器发现的细节,而方面可以(在其他事情中)封装中间件服务调用的细节——例如,提供事务和安全性管理。因为依赖项插入和AOP都会形成更简单、更容易测试的基于对象的应用程序,所以想把它们结合在一起使用是很自然的。方面可以帮助把依赖项插入的能力带到更广的对象和服务中,而依赖项插入可以用来对方面本身进行配置。
在这篇文章中,我将介绍如何把Spring框架的依赖项插入与用ASPectJ5编写的方面有效地结合在一起。我假设您拥有基本的AOP知识(如果没有这方面知识,可以在参考资料中找到一些良好的起点),所以我的讨论将从对基于依赖项插入的解决方案中包含的关键角色和职责的分析开始。从这里,我将介绍如何通过依赖项插入配置单体(singleton)方面。因为配置非单体方面与配置域对象共享许多公共内容,所以后面我会研究一个应用于这两者的简单解决方案。总结这篇文章时,我会介绍如何为多个高级依赖项插入场景使用方面,其中包括基于接口的插入和重复插入。
什么是依赖项插入?
在Domain-DrivenDesign一书中,EricEvans讨论了如何把对象与建立对象的配置和关联的细节隐藏起来:
对象的大部分威力在于对象内部复杂的配置和关联。应当对对象进行提炼,直到与对象的意义或者在交互中支持对象的作用无关的东西都不存在为止。这个中间循环的责任很多。如果让复杂对象负责自己的创建,就会出现问题。
Evans接着提供了一个汽车引擎的示例:它的众多部件一起协作,执行引擎的职责。虽然可以把引擎块想像成把一组活塞插入气缸,但是这样的设计会把引擎明显地弄复杂。相反,技工或机器人装配引擎,引擎本身只考虑自己的操作。
虽然这个示例是我从书中介绍用于复杂对象创建的工厂概念一节中取出的,但是我们也可以用这个概念解释依赖项插入技术的动机。
从协作到合约
关于依赖项插入的经典介绍,请参阅MartinFowler的“InversionofControlContainersandtheDependencyInjectionPattern”。关于使用Spring的依赖项插入的更多内容,请参阅ProfessionalJavaDevelopmentwiththeSpringFramework。这两者的链接都在参考资料中。
针对这篇文章的目的,可以把依赖项插入想像成对象和对象的执行环境之间的合约。对象(执行ResourceConsumer、Collaborator和ServiceClient的其中一个角色或全部角色)同意不出去搜索自己需要的资源、它与之协作的合作伙伴或它使用的服务。相反,对象提供一种机制,让这些依赖项可以提供给它。接下来,执行环境同意在对象需要它的依赖项之前,向对象提供所有的依赖项。
解析依赖项的方法在不同的场景中各有不同。例如,在单元测试用例中,对象的执行环境是测试用例本身,所以测试设置代码有责任直接满足依赖项。在集成测试或应用程序在生产环境时,代理负责寻找满足对象依赖项的资源,并把它们传递给对象。代理的角色通常是由轻量级容器扮演的,例如Spring框架。不管依赖项是如何解析的,被配置的对象通常不知道这类细节。在第二个示例中,它可能还不知道代理的存在。
代理(例如Spring框架)有四个关键职责,在整篇文章中我将不断提到这些职责,它们是:
确定对象需要配置(通常因为对象刚刚创建)确定对象的依赖项发现满足这些依赖项的对象用对象的依赖项对它进行配置 从下面的各种依赖项插入解决方案可以看出,解决这些职责有多种策略。