Python中如何实现类似Java IOC的依赖注入工具?

git 地址: https://github.com/lecher23/pioc

欢迎大家提意见~
Python中如何实现类似Java IOC的依赖注入工具?

20 回复

好像深入学习修饰器功能


Python里实现类似Java Spring的IOC容器,可以用injector库,它提供了类型安全的依赖注入。下面是一个完整示例:

from injector import Injector, inject, Module, singleton

# 定义服务接口和实现
class DatabaseService:
    def query(self):
        return "data from database"

class CacheService:
    def get(self, key):
        return f"cached_{key}"

# 业务类通过构造函数声明依赖
class UserService:
    @inject
    def __init__(self, db: DatabaseService, cache: CacheService):
        self.db = db
        self.cache = cache
    
    def get_user(self, user_id):
        data = self.db.query()
        cached = self.cache.get(user_id)
        return f"{data} + {cached}"

# 配置模块定义依赖关系
class AppModule(Module):
    def configure(self, binder):
        binder.bind(DatabaseService, to=DatabaseService, scope=singleton)
        binder.bind(CacheService, to=CacheService, scope=singleton)

# 使用容器
injector = Injector([AppModule()])
user_service = injector.get(UserService)

print(user_service.get_user("123"))  # 输出: data from database + cached_123

关键点:

  1. @inject装饰器标记需要注入的构造函数
  2. 通过Module配置接口与实现的绑定关系
  3. singleton作用域确保单例模式
  4. 容器自动解析依赖链并注入

如果不想用第三方库,也可以自己实现一个简单的IOC容器,通过注册表和反射来管理依赖。不过injector库更接近Java Spring的风格,支持类型提示和生命周期管理。

injector库就行,够用了。

加油,自己多写几个装饰器就了解了

https://stackoverflow.com/a/2462076

Python 中在 A 模块中先创建一个对象,之后在 B 模块中使用 import object from A 就可以获取到对象了额 O__O "…

其实我这个注入工具主要是解藕服务,以及统一管理一些服务器资源拉,比如说我一个应用程序内部有很多的服务,我希望通过它就可以实现服务的管理,替换的时候只需要更换一个地方声明服务就好了…

python 里也可以直接替换的。。

这不就是单例模式嘛,依赖注入可以有多种方式

而且依赖注入容器主要解决的是复杂的依赖关系,比如 A 依赖 B、C,C 依赖 D、E,B 又依赖 E、F,总不能一个一个去替换吧。

首先,你要认识到:喜欢搞 py 的人自认为很高雅!
你怎么能说你是抄的 java 呢?
楼主,你要感谢我这一层的存在,不然会有很多喜欢搞 py 的人来 gang 你。

Python 真的需要这种 style 的 design pattern 嘛?

我觉得你这里要实现的功能,用 thread-local context 就能实现啊?
thread-local context 而且是 python 里面大量被使用的 design pattern,python community 很熟悉它。
对比你这里提到的 java style 的依赖反转,其实在 python community 是个非常陌生的概念。

thread-local context 的例子:

* Flask: request, response, current_app
* Celery: current_app, current_task
* TensorFlow: default_graph, default_session

好吧,我上面提到的 thread-local context 是为了能够动态修改某个子模块的外部依赖环境。

如果你只是为了解决复杂的依赖关系,额,python 的 import 不就可以了嘛?

毕竟我可以在 function level 进行 import:

A.py:

from B import f

B.py:

def f():
…import A

最后提一句,thread-local context 可以以 stack 的方式实现,这样的话就可以配合 with context 来临时把一个 context 推到栈顶,临时替换某个子模块的外部环境,然后退出 with 的时候也同时退出这个 context。这个设计非常之好用。

说的这么玄乎,我也是醉了,php 的概念为什么非得炒作?这只是很普通的设计模式吧

感谢楼上现身说法。
楼主,现在你相信我了吗

哈哈,就服你

感谢不吝赐教哈,thread-local context 这个我还真没仔细研究过,改天去啃一下。不过我觉得这个工具在我目前的开发中还是挺有用的,虽然从大家的意见来看的确有很多种实现方式。。。

可能我不是很理解依赖注入的设计模式,我的理解是依赖注入需要靠 interface 实现的么,方便替换实现内容。但是 Python 的动态类型不需要这种笨重的方法…

为什么需要搞得像 Java 一样复杂的语法,装饰器又不是注解。想注入某些对象,完全可以在参数列表里面加默认值,这可是 Python 这些动态语言的大特性啊,Java 是因为是静态才需要搞成这样啊。

我并不觉得这个语法复杂,而且在解决系统各个服务的依赖方面,这个方式起码让我觉得比自己在构造服务的时候传参数方便很多…

回到顶部