http://www.blogcn.com/user8/flier_lu/index.html?id=1311788&run=.0CEEA16
<Shared Source CLI Essentials>一书的作者Ted Neward最近在其blog上发表了一篇关于AOP实现思路的文章<Setting the Story Straight: AOP != Interception>,引起了广泛的争议。
他认为虽然Interception模式和AOP看起来很像,但并不等同。将AOP等同于Interception,类似于将OOP等同于数据结构加上函数指针。
以下为引用:
..., to understand AOP as Interception is like thinking OOP is data structs plus a bunch of function pointers. Just as we didn''t understand objects until we got past the idea that objects are "just code and data", ...
为证明这个观点,他首先定义了AOP和Interception的概念。这一点很值得我们学习,国内很多论坛上常常莫名其妙大家大吵一架,其实说的根本不是一个东西,呵呵
以下为引用:
Aspect-Oriented Programming:
"Aspect-oriented software development is a new technology for separation of concerns (SOC) in software development. The techniques of AOSD make it possible to modularize crosscutting aspects of a system." --AOSD homepage
"The central idea of AOP is that while the hierarchical modularity mechanisms of object-oriented languages are extremely useful, they are inherently unable to modularize all concerns of interest in complex systems. Instead, we believe that in the implementation of any complex system, there will be concerns that inherently crosscut the natural modularity of the rest of the implementation.
"AOP does for crosscutting concerns what OOP has done for object encapsulation and inheritance--it provides language mechanisms that explicitly capture crosscutting structure. This makes it possible to program crosscutting concerns in a modular way, and achieve the usual benefits of improved modularity: simpler code that is easier to develop and maintain, and that has greater potential for reuse. We call a well modularized crosscutting concern an aspect." --An Overview of AspectJInterception: "The Interceptor architectural pattern allows services to be added transparently to a framework and triggered automatically when certain events occur." --Patterns of Software Architecture, Vol 2 by Schmidt et. al, p. 109
此外他还定义了概念的分离以及横切(Cross-cutting)概念。
在讨论Interception和AOP时,他指出Interception在实现AOP时所受的限制。
以下为引用:
1.Explicit support from the system for interception. POSA2 calls it the framework, COM+, .NET, servlets and EJB do it at container boundaries, but the underlying idea is the same--somewhere, some kind of construct (what I''ll colloquially refer to as "The Plumbing") is what''s providing the interception behavior, explicitly routing the call flow through the Interceptor as part of normal processing. This means that only those artifacts understood by the plumbing as first-class citizens can be so Intercepted--anything that''s not within the purview of the plumbing cannot be intercepted. For example, in the servlet framework (starting from the 2.3 specification), Interception is provided via filters, allowing servlet authors the opportunity to "hook" the request and response to a servlet or JSP (or any other URL, for that matter). However, Interception can only apply to URL request/response semantics, so filters cannot, for example, intercept calls to ordinary Java classes or calls via other channels, like RMI, to other systems.2.The notion of a request/response channel. Interception implicitly relies heavily on the idea of request/response semantics, since interceptors almost always fire around method entry and exit. This means that a large number of object interaction semantics are left untouched and unavailable. (If this is a bit abstract, hang on--this will make more sense later.)
3.Interception is almost universally a runtime construct. POSA2 makes explicit reference to this fact, citing the idea that these services won''t always be desired or necessary for all cases, so the behavior from the Interceptor cannot be layered in statically--it needs to be registered at runtime. Unfortunately, this also implies a certain amount of runtime overhead, particularly if the interceptor''s event model is fairly coarse- grained. For example, in the .NET context object architecture, method calls both into and out of an object inside of a context can be intercepted via the IMessageSink-and-friends architecture. However, once registered, a context interceptor must be invoked for every method call in and/or out of the context; there is no way to specify that the interceptor is only valid for "methods of this type".
首先是必须由被Interception的系统框架提供显式的支持;其次是基于请求/应答策略;最后普遍需要动态构造。当然不同环境中还是提供了其他的实现途径,例如Java/CLR都提供了动态透明代理(Dynamic Proxy)的机制,动态对目标进行封装。
而AOP则是基于两个构造定义的:join points和advice。前者指明在哪儿插入;后者是插入的内容。故而AOP具有如下的属性
以下为引用:
1.AOP systems need no underlying "plumbing". This statement is somewhat controversial, since obviously something needs to do the aspect weaving at some point in the execution lifecycle. However, this frequently isn''t a runtime construct, but a compile-time or load-time operation; for example, AspectJ is a compiler, performing all the weaving at compile-time.2.AOP systems can weave against anything. An AOP system is limited only by its join point model--for example, AspectJ can easily define an object-relational persistence aspect that weaves around JavaBean classes, such that any field-get access against a non-transient field would immediately trigger a database access to obtain the latest version of that field, and any field-set access against a non-transient field would immediately trigger a database access to set that value into the database. While the performance of such an aspect system would be horrendous (think of all the round-trips!), the fact that this could be done against any JavaBean class, which could be used in a servlet system, a Swing app, or a J2ME device is powerful.
作者紧接着举了一个检测SQL注入攻击(injection attacks)的例子,指出针对JDBC中PreparedStatement函数无法通过简单方法完成Interception,这与AOP的原意是不相符的。
最后,作者得出结论。
1.在Interception和AOP之间是可以有中间状态的。例如John Lam的CLAW实现就完成了对.NET CIL代码载入时的aspect code-weaving。这种方法既能够以编译形式表达自己,又能只针对小粒度的目标方法显式完成功能,而不需要Interception那样由系统提供支持、只能针对大粒度的类、并且损失运行时的效率。
2.AOP可以很自然地使用Interception作为其实现机制。例如JBoss的实现就是使用Interception框架解决问题的最好实例。
3.Interception可以被看作是AOP的一种简单形式,类似于VB是OOP的一种简单形式。Interception是了解AOP的一个重要步骤,但不是终点。Interception最适用于组件边界(component boundaries)上,而AOP完全适用于组件边界内。
可以说这篇文章还是言之有理的,但容易引起争论的地方过多了,呵呵
Rickard Oberg在其回应文章AOP != AspectJ中批驳了Ted的一些观点。主要目标是Ted虽然没有明说,但是影射AspectJ的很多特性为AOP的必要特性。
首先,Ted认为AOP不应有底层的薄记工作(underlying "plumbing"),而Rickard则指出AspectJ实际上也有这种工作,只不过由AspectJ的编译器自动对每个对象完成了。个人认为这儿Ted的意思可能是指AOP不应有需要使用者完成的薄记工作,而使用编译器或其他程序自动完成的则可以忽略。
其次,Ted认为AOP系统可以针对任意粒度的任意对象,而Rickard则指出如果只使用interception时并不意味着就不是AOP了,而只是使用了一个限制较为严格的AOP。同时如果没有性能、C/S模型、序列化等需求时,也没有必要非得用AspectJ。这点上我还是比较赞同Rickard的观点的,Interception和AspectJ只是实现AOP的两种思路而已,没有冲突的。
然后,Rickard指出Ted给出的那个检测SQL注入攻击的例子实际上是一个反模式(anti-pattern),呵呵。
最好,Ted认为AspectJ能够适用于组件边界内,但Rickard指出,实际上很多情况下不应该介入到组件边界内。这种嵌入实际上是一种反模式,应该使用其他的模式予以回避。而在性能方面,Rickard认为Interception模式耗费的时间也是可以接受的。
to be continue...