yadi——又一个依赖注入框架

yadi-framework的Python项目详细描述


build statusPypi

亚迪

又一个依赖注入框架

yadi是一个依赖注入框架。它同时支持类和 以声明的方式运行。

安装

pip install yadi-framework

基本示例

这是一个简单的注射示例:

fromyadi.context_implimportDEFAULT_CONTEXTfromyadi.decoratorsimportinjectfromyadi.typesimportYadi@inject()classComponent1:pass@inject()classComponent2:def__init__(self,c1:Yadi[Component1]):self.c1=c1@inject()classComponent3:def__init__(self,c1:Yadi[Component1]):self.c1=c1c2=DEFAULT_CONTEXT.get_bean(Component2)# type: Component2c3=DEFAULT_CONTEXT.get_bean(Component3)# type: Component3print(Component1istype(c2.c1))# Trueprint(c2.c1isc3.c1)# True

下面是一个如何注入函数的示例:

fromyadi.context_implimportDEFAULT_CONTEXTfromyadi.decoratorsimportinjectfromyadi.typesimportYadi@inject()classComponent:pass@inject(name='another_function')defh(x,y,z=None):assertisinstance(x,Component)print('Function h:',type(x))@inject(name='my_function')deff(a:Yadi[Component],b,c:Yadi['another_function']=None,d:str=None):c(a,b,z=d)DEFAULT_CONTEXT.get_bean('my_function')(23,d=5)# Function h: <class '__main__.Component'>

范围

默认情况下,所有bean都保存为singleton。每一个单子都是 存储在其上下文中,即每个实例都有一个实例。 上下文实例

或者,可以将bean保存为原型,即 每当引用bean时都会生成不同的实例。

fromyadiimportcontextfromyadiimporttypesfromyadi.context_implimportDEFAULT_CONTEXTfromyadi.decoratorsimportinject@inject(scope=context.PROTOTYPE,name='a component 1')classComponent1:pass@inject(name='a component 2')classComponent2:def__init__(self,f1:types.Yadi[Component1],f2:types.Yadi['a component 1']):self.f1,self.f2=f1,f2@inject(name='a component 3')classComponent3:def__init__(self,f1:types.Yadi[Component1],f2:types.Yadi['a component 1']):self.f1,self.f2=f1,f2c2=DEFAULT_CONTEXT.get_bean('a component 2')# type: Component2c3=DEFAULT_CONTEXT.get_bean('a component 3')# type: Component3print(isinstance(c2.f1,Component1))# Trueprint(isinstance(c2.f2,Component1))# Trueprint(isinstance(c3.f1,Component1))# Trueprint(isinstance(c3.f2,Component1))# Trueprint(c2.f1==c2.f2)# Falseprint(c3.f1==c3.f2)# Falseprint(c2.f1==c3.f1)# Falseprint(c2.f1==c3.f2)# Falseprint(c2.f2==c3.f1)# Falseprint(c2.f2==c3.f2)# False

还可以定义自定义范围并将其添加到上下文中。

这里是线程本地作用域的一个示例:

importthreadingfromyadi.contextimportScopefromyadi.context_implimportDEFAULT_CONTEXTfromyadi.decoratorsimportinjectclassThreadLocalScope(Scope):def__init__(self):self._tl=threading.local()defget(self,key:str):returngetattr(self._tl,key,None)defset(self,key:str,obj:object):setattr(self._tl,key,obj)@propertydefname(self):return'threadlocal'@propertydeflevel(self):return100DEFAULT_CONTEXT.add_scope(ThreadLocalScope())@inject(scope='threadlocal',name='a component 1')classComponent1:passc1=DEFAULT_CONTEXT.get_bean('a component 1')c1_2=DEFAULT_CONTEXT.get_bean('a component 1')thread_c1=[]c1_t=Nonedef_f():globalc1_tc1_t=DEFAULT_CONTEXT.get_bean('a component 1')print(c1_t==DEFAULT_CONTEXT.get_bean('a component 1'))# Truethread_c1.append(c1_t)t=threading.Thread(target=_f)t.start()t.join()print(c1==c1_2)# Trueprint(c1==c1_t)# False

^ {STR 1 } $作用域代理< /强>

假设在单例中注入一个线程本地作用域bean。作为一个 结果,共享同一个单例的不同线程不应共享 同一线程本地bean,这是不可能的。

为了解决这个问题,yadi在注入的 在上下文中委托对当前bean的任何访问的bean。

一般来说,作用域有一个level属性:如果注入的bean 具有比容器bean更高的作用域级别,注入的bean是 包装到作用域代理中。

这是一个范围代理的例子(不用担心,你不必 做任何事来让它工作)。

importrandomimportthreadingfromyadi.bean_factoriesimport_ScopedProxyfromyadi.contextimportScopefromyadi.context_implimportDEFAULT_CONTEXTfromyadi.decoratorsimportinjectfromyadi.typesimportYadiclassThreadLocalScope(Scope):def__init__(self):self._tl=threading.local()defget(self,key:str):returngetattr(self._tl,key,None)defset(self,key:str,obj:object):setattr(self._tl,key,obj)@propertydefname(self):return'threadlocal'@propertydeflevel(self):return100DEFAULT_CONTEXT.add_scope(ThreadLocalScope())@inject(scope='threadlocal')classComponent1:def__init__(self):self.object_id=random.randint(0,1000000)@inject(name='a component')classComponent2:def__init__(self,f1:Yadi[Component1]):self.f1=f1component=DEFAULT_CONTEXT.get_bean('a component')component_thread_id=[]print('Main thread, scoped proxy type',type(component.f1)==_ScopedProxy)# Main thread, scoped proxy type Truedef_f():component_thread=DEFAULT_CONTEXT.get_bean('a component')print('Subthread, scoped proxy type',type(component_thread.f1)==_ScopedProxy)component_thread_id.append(component_thread.f1.object_id)print('Subthread, bean id',component_thread.f1.object_id==DEFAULT_CONTEXT.get_bean('a component').f1.object_id)t=threading.Thread(target=_f)t.start()t.join()# Subthread, scoped proxy type True# Subthread, bean id Trueprint('Main thread, bean id',component.f1.object_id==component_thread_id[0])# Main thread, bean id False

上下文

所有组件都保存在上下文中。

默认情况下,injectdecorator将bean实例保存在 yadi.context_impl.DEFAULT_CONTEXT

您可能希望实例化一个新上下文并将其作为^{tt4}传递$ injectdecorator的关键字参数。

生命周期

只要创建一个bean,就可以触发它们。在 为了定义要触发的方法,必须修饰 它们带有post_create,如下所示:

fromyadi.context_implimportDEFAULT_CONTEXTfromyadi.decoratorsimportinject,post_createfromyadi.typesimportYadi@inject()classComponent1:pass@inject()classComponent2:def__init__(self,c1:Yadi[Component1]):self.c1=c1self.invoked_post_create=0@post_createdeffinished_creating(self):print('Component 1:',self.c1)# Component 1: <__main__.Component1 object at 0x7f42e90d2e48>self.invoked_post_create+=1component_2=DEFAULT_CONTEXT.get_bean(Component2)# type: Component2print('post_create invokations:',component_2.invoked_post_create)# post_create invokations: 1DEFAULT_CONTEXT.get_bean(Component2)print('post_create invokations:',component_2.invoked_post_create)# post_create invokations: 1

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
如何在Java中创建固定大小的泛型数组?   javascript Paypal Braintree订阅付款   使用BufferedReader和PrintWriter实现java数据持久化?   类似于iCloud的java唯一google id   java使用网格布局和抓取组合框   java我的while循环无限运行,当我检查它时,它说while循环没有主体,而我认为它显然没有主体   java LWJGL碰撞3D OpenGL   java将Tibco RV切换到WebSphere MQ?   java如何使用Postman从curl发布REST   java是超级的,在通用通配符中是独占的吗?   在swing 1.5中,java在指定时间后自动关闭非模态对话框   java PrimeFaces饼图在JSF 2.0中不显示   java如何在Spring MVC中提供带有xml配置的默认bean实现?   java在eclipse中使用按钮关闭JFrame   java Sqoop jar已弃用   Java中的Getter方法