面向方面的编程实例
任何人都可以发表一个面向方面编程(AOP), 不logging的例子吗?
我已经看了几个资源,但所有的例子都是微不足道的日志logging。 有什么用?
其中一个例子是直接从这个面向方面的程序devise:模块化激进研究,Youtubevideo被绘制到显示器上。 在这个例子中,你有一个绘图程序,由点,形状等组成,当这些对象发生变化时,你需要告诉显示器更新自己。 没有在一个方面处理它,你最终会重复一下自己。
正如我所了解的,AOP的创build是为了不重复自己的交叉问题,这可能与业务逻辑无关。 有了方面,您可以将这些问题模块化。 其中一个例子就是日志logging,但是有很多不同的东西你可能会重复。 它一直在发展,并没有更多的面向方面的编程,但也有面向方面的build模。
有关面向方面编程的更多信息可以从这些资源中find:
- 读书:
- 维基百科 – 面向方面的编程
- 听:
- 软件工程无线电 – 第106集:AOP简介
- 软件工程收音机 – 第11集:采访Gregor Kiczales
- 观看:
- Google Video – Anurag Mendhekar:面向方面的编程(Dan Friedman诞辰60周年)
- Youtube – 面向方面的编程:模块化的激进研究
- Youtube – 面向方面的build模 – 它是什么,它有什么好处
安全
- 注入检查权限并阻止访问的代码
对于asp.net webcontrols / webparts Friendlier错误消息
- 注入捕获exception的代码,并在编译时编写堆栈跟踪,或者在错误编译时编写友好的消息(例如: asp.net / MOSS2007(含代码)的透明genericsexception处理 )
性能
- 注入设置perf计数器的代码,以获得应用程序速度缓慢的概述
validation:
[NotNull] public string Property1 { get; set; } [Length(Min = 10, Max = 20)] public string Property2 { get; set; } [Regex(Expression = @"[abc]{2}")] public string Property3 { get; set; }
撤消 – 我正在调用支持撤消操作的第三方程序集。 它要求调用者创build一个撤消上下文,调用程序集中的一些方法,然后销毁撤消上下文。 上下文可以嵌套。 另外,如果创build了上下文,但仍处于需要重新启动应用程序的不良状态。
通常使用撤消,我会写这样的东西
void foo() { int id = lib.create_undo_context(); try { lib.performsomeaction(); lib.performsomeaction(); lib.performsomeaction(); } finally { lib.destroy_undo_context(id); } }
使用PostSharp我定义了一个名为[Undo]的属性,在方法启动时创build撤消上下文,并在方法退出时销毁它(即使抛出exception) – 所以代码看起来像这样
[Undo] void foo() { lib.performsomeaction(); lib.performsomeaction(); lib.performsomeaction(); }
实现这一点比我所展示的要复杂一点,因为我确保即使在有嵌套撤销上下文的情况下,所有的撤消上下文都被清除 – 但是你明白了。
Java和AspectJ中的devise模式实现(Hannemann和Kiczales): http : //www.cs.ubc.ca/labs/spl/papers/2002/oopsla02-patterns.pdf
本文展示了如何使用AspectJ在Java中以更好的方式实现一些GoFdevise模式
另一个典型的例子(如日志logging)是caching。 但是其他例子更有趣。
dependency injection
严格来说,dependency injection只不过是一个横切关注。 许多dependency injection框架使用如下的基于属性的编程风格:
public class Car:IDisposable { [Inject] public IGearBox Gearbox { get; set; } ... }
[Inject]属性也可以被devise为一个不依赖于外部框架的方面。
安全性 – 在执行某些方法之前检查用户是否具有适当的权限。
Java中不能有多重inheritance。 但是通过使用AOP,你可以“有限”多重inheritance。 尝试谷歌这看到一些例子。
我也同意艾维德。 Hannemann和Kiczales的论文非常适合学习devise模式的基础知识,并获得一些很好的AOP范例。
公共不变检查。 由于PostSharp 1.5将带有方面的inheritance,即使通过接口,也会带来很多新的机会。
我的相册使用aspectj三件事情:
- 实现观察者“模式”作为可重用的一段代码。
- 销毁特定types呼叫的会话。
- 发生突变时在DTO上设置脏标志。
第一个,特别是在AOP的Google技术讨论中非常直接。 这与大多数人所考虑的方式不同。 绝对推荐观看,如果你有兴趣如何使用它的好。
我使用了面向方面的编程来实现关键字search引擎。 这更像是一个实验,但它显示了如何将AOP用于logging和跟踪以外的目的。
基本上:
(i)引擎的用户将他/她的课程标记为KeywordSearchable,
(ii)引擎开始跟踪这些KeywordSearchable实例的创build和销毁,
(iii)引擎从这些KeywordSearchable对象中提取关键字,
(iv)给定对象和关键字,algorithm负责search。
有关此更多详细信息可以在http://montrealistic.blogspot.com/2011/08/aspect-oriented-implementation-of.htmlfind。;
AOP的例子:
- 算术expression式的parsing器和评估器。 这可以使用访问者模式进行编程,但我相信这些方面是更好的select。
- 一个简单的文本编辑器,其中一些pipe理任务(例如,维护“文件已更改”标志和窗口标题)被视为单独的方面。
- string的数据结构,其中string表示为树,以便可以在不进行复制的情况下实现拼接和子stringselect。 为了保持效率,树木有时需要重新平衡; 平衡代码被视为一个方面。
假设您想在域模型的方法中logging一条消息:
示例:不使用AOP进行logging:
namespace Examples\Forum\Domain\Model; class Forum { /** * @Flow\Inject * @var \Examples\Forum\Logger\ApplicationLoggerInterface */ protected $applicationLogger; /** * Delete a forum post and log operation * * @param \Examples\Forum\Domain\Model\Post $post * @return void */ public function deletePost(Post $post) { $this->applicationLogger->log('Removing post ' . $post->getTitle(), LOG_INFO); $this->posts->remove($post); } }
如果你必须在很多地方这样做,日志logging将成为你的领域模型逻辑的一部分。 你将不得不在你的模型中注入所有的日志依赖。 由于日志并不是领域模型应该关心的东西,这就是一个非function性需求和所谓的横切关注的例子。
使用AOP,模型中的代码不会logging日志。 它将专注于业务逻辑。
交易pipe理。
在我看来,您不希望可能属于交易一部分的对象知道它们在交易中。 使用AOP,您可以根据需要将对象组合到事务中,而不需要事务中的对象知道事务处于事务中,甚至不需要知道AOP框架的存在。