昨天在答一個(gè)問題時(shí),看題不清答錯(cuò)了,不過卻讓我花了點(diǎn)時(shí)間想如何實(shí)現(xiàn)簡單的AOP。
在其它語言里實(shí)現(xiàn)AOP的確比較麻煩,java要用到動(dòng)態(tài)proxy,如果是C++,除了從源碼上修改還真沒好辦法,aspectc就是這么做的。那么ruby里面如何實(shí)現(xiàn)呢?
由于ruby是動(dòng)態(tài)腳本語言,運(yùn)行期可以把一個(gè)方法改名,也可以構(gòu)造一個(gè)字符串動(dòng)態(tài)生成方法,那么實(shí)現(xiàn)這個(gè)就不是難事了。
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
??end
end
使用時(shí)只需要在類里面include這個(gè)模塊就行了,相當(dāng)于mixin的功能。
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,?:c
end
注意,由于使用execute_before時(shí)后面幾個(gè)方法必須要有定義,所以必須放在后面,否則就會(huì)出錯(cuò)。