昨天在答一个问题时,看题不清答错了,不过却让我花了点时间想如何实现简单的AOP。在其它语言里实现AOP的确比较麻烦,java要用到动态proxy,如果是C++,除了从源码上修改还真没好办法,aspectc就是这么做的。那么ruby里面如何实现呢?由于ruby是动态脚本语言,运行期可以把一个方法改名,也可以构造一个字符串动态生成方法,那么实现这个就不是难事了。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->module ExecuteBefore def self.included(base) base.extend(ClassMethods) end module ClassMethods def execute_before(before_method, *methods) methods.flatten.map(&:to_sym).each do |method| alias_method "#{method}_old".to_sym, method class_eval <<->eval_end def #{method}(*args) #{before_method}(*args) #{method}_old(*args) end eval_end end end endend使用时只需要在类里面include这个模块就行了,相当于mixin的功能。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->class TestController < ApplicationController def index a(1) b(1,2) c(1,2,3) render :text => 'hello' end protected def log(*args) puts "log: #{args.map(&:to_s).join(', ')}" end def a(a) end def b(a,b) end def c(a,b,c) end include ExecuteBefore execute_before :log, :a, :b, :cend注意,由于使用execute_before时后面几个方法必须要有定义,所以必须放在后面,否则就会出错。 |