前言
flask框架自带的代理对象有四个,分别是request,session,g和current_app,各自的含义我们在前面已经详细分析过。使用代理而不是显式的对象的主要目的在于这四个对象使用太过频繁,贯穿整个请求周期,显式传递很容易造成循环导入的问题,需要一个第三方的对象来进行解耦。
代理模式简介
代理模式是程序设计的一种结构模式,其目的是使调用者和执行者之间不发生直接的关系,而是使用一个代理人,这样调用者和执行者就进行了解耦,可以避免许多的问题。
代理模式使用的场景:
-
为真实目标类创建一个对象的代价是昂贵的,而创建代理类很简单;
-
对象必须防止被用户直接使用。
-
当实际请求的时候,为真实目标类创建一个对象会有延迟。
class Boss(object):
def task1(self):
print('this is task1')
def task2(self):
print('this is task2')
class Proxy(object):
def __init__(self, obj):
self.proxy = obj
def task1(self):
self.proxy.task1()
def task2(self):
self.proxy.task2()
proxy_boss = Proxy(Boss())
class Client(object):
def do_something(self):
proxy_boss.task1()
if __name__ == '__main__':
c = Client()
c.do_something()
上述的Boss实例不需要显式传递,受到了保护;Proxy对象相当于一个接口的作用。
LocalProxy代理对象
LocalProxy就是flask框架的werkzeug工具实现的一个代理对象,它接收一个可调用的无参数函数作为参数,内部实现了object对象所有的魔法方法的重写,理论上可以代理任何的对象,不管这个对象的结构是怎么样的。
class LocalProxy(object):
def __init__(self, local, name=None):
object.__setattr__(self, '_LocalProxy__local', local)
object.__setattr__(self, '__name__', name)
def _get_current_object(self):
if not hasattr(self.__local, '__release_local__'):
return self.__local() # 代理对象local必须是可调用的
try:
return getattr(self.__local, self.__name__)
except AttributeError:
raise RuntimeError('no object bound to %s' % self.__name__)
如果我们想在项目中的任何地方使用我们自己的全局代理对象,我们可以这样做:
# myproxy.py
from werkzeug.local import LocalProxy
class Boss(object):
def pop(self):
print('Ok')
return 'OK'
class OtherObj(object):
def __init__(self,Obj):
self.real_obj = Obj()
other = OtherObj(Boss)
def get_boss(Obj=None):
return Obj.real_obj
proxy_boss = LocalProxy(partial(get_boss, other))
get_boss这种形式是动态代理,也就是说在进程运行中由于OtherObj的real_obj属性可能发生变化,proxy_boss代理的对象可能发生改变。