python aop
参考文章:https://www.jianshu.com/p/4c588eec1be1
python的aop由@语法糖来实现,@语法糖就是个装饰器模式。能够这么实现是因为在python中函数就是对象。因此,对象:
- 可以赋值给一个变量
- 可以在其他函数中定义
- 函数可以返回另一个函数
- 函数作为参数传递
直接给个demo:
# 装饰器就是把其他函数作为参数的函数
def my_new_decorator(a_function_to_decorate):
def the_wrapper_function():
print "Before the function runs"
a_function_to_decorate()
print "After the function runs"
return the_wrapper_function
def a_stand_alone_function():
print "I am a stand alone function, don't you dare modify me"
a_stand_alone_function()
# 输出: I am a stand alone function, don't you dare modify me
# 相当于the_wrapper_function() & a_function_to_dacorate = a_stand_alone_function
a_function_decorated = my_new_decorator(a_stand_alone_function)
a_function_decorated()
# 输出:
# Before the function runs
# I am a stand alone function, don't you dare modify me
# After the function runs
所以上面的语法使用语法糖之后就是:
@my_new_decorator
def another_stand_alone_function():
print "Leave me alone"
another_stand_alone_function()
像java一样一个注解就能解决的事情,那么java aop的时候函数是有参数的, python呢?
# 可以装饰带参数的函数
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print "I got args! Look:", arg1, arg2
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print "My name is", first_name, last_name
print_full_name("Peter", "Venkman")
# 输出:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
好,但是java aop和参数是没有关系的,这里就是2个参数,怎么搞? kwargs?即使是kwargs对被装饰的函数也是有限定要求的。
go aop
修改函数
这里有个go版本的aop:https://github.com/gogap/aop
go的aop应该是很多人会单独去实现,但是官方并没有标准的aop实现。
像这个项目的readme之中的例子:
func (p *Auth) Login(userName string, password string) bool {
p.Before(userName, password)
defer p.After(userName, password)
if userName == "zeal" && password == "gogap" {
return true
}
return false
}
这个并不是aop只是修改了函数,不是python这种形式
reflect.MakeFunc
如果仿照python这么写的话:
func a_function_to_decorate() {
fmt.Println("Hello world")
}
func my_new_decorator(a_function_to_decorate interface{}) {
fmt.Println("before")
// error: cannot call non-function a_function_to_decorate (type interface {})
a_function_to_decorate()
fmt.Println("after")
}
func main() {
my_new_decorator(a_function_to_decorate)
}
用interface传入一个函数,但是go是静态语言interface{}并不是function实现了空interface{},但是interface{}并不是function。
所以怎么办呢,必须确认传入的参数是function,之后才能使用某种方式来进行调用。那就要用到反射了。
func MakeTimedFunction(f interface{}) interface{} {
rf := reflect.TypeOf(f)
if rf.Kind() != reflect.Func {
panic("非Reflect.Func")
}
vf := reflect.ValueOf(f)
wrapperF := reflect.MakeFunc(rf, func(in []reflect.Value) []reflect.Value {
start := time.Now()
out := vf.Call(in)
end := time.Now()
fmt.Printf("calling %s took %v\n", runtime.FuncForPC(vf.Pointer()).Name(), end.Sub(start))
return out
})
return wrapperF.Interface()
}
func time1() {
fmt.Println("time1Func===starting")
time.Sleep(1 * time.Second)
fmt.Println("time1Func===ending")
}
func time2(a int) int {
fmt.Println("time2Func===starting")
time.Sleep(time.Duration(a) * time.Second)
result := a * 2
fmt.Println("time2Func===ending")
return result
}
func main() {
timed := MakeTimedFunction(time1).(func())
timed()
timedToo := MakeTimedFunction(time2).(func(int) int)
time2Val := timedToo(5)
fmt.Println(time2Val)
}
go版本monkey patch
参考:https://blog.csdn.net/sqxww123/article/details/101777075
go的monkeypatch先不研究了
java aop
待续