当前位置: 首页 > 科技观察

[服务器]PHP是如何实现依赖注入的?

时间:2023-03-12 13:01:37 科技观察

依赖注入(DependencyInjection,简称DI),也称为InversionofControl,简称IOC,是目前主流框架中实现的,比如ThinkPHP、Laravel等。什么是依赖注入?举个简单的例子:(1)原始社会,几乎没有社会分工。需要斧头的人(调用者)只能自己磨斧头(被调用者)。(2)进入工业社会,出现工厂。斧头不再是普通人完成,而是在工厂生产。这时候需要斧头的人(调用者)就找到了工厂,买了斧头,根本不关心斧头的制造过程。(3)进入“按需分配”社会,需要斧头的人不用找工厂,而是坐在家里发出一个简单的指令:他们需要一把斧头。斧头自然而然的出现在了他的面前。在第一种情况下,实例的调用者创建被调用实例,这必然要求被调用类出现在调用者的代码中。两者之间无法实现松耦合。第二种情况,调用者不需要关心被调用者的具体实现过程,只需要找到一个符合一定标准(接口)的实例即可使用。这时调用的代码是面向接口编程,可以解耦调用者和被调用者,这也是工厂模式被广泛应用的原因。但是调用者需要自己定位工厂,调用者耦合具体的工厂。第三种情况,调用者不需要自己定位工厂。当程序运行到需要被调用者的时候,依赖注入容器会自动提供被调用者实例。实际上,调用者和被调用者都在依赖注入容器的管理之下,两者之间的依赖是由依赖注入容器提供的。因此调用者和被调用者之间的耦合度进一步降低,使应用程序更易于维护,这就是依赖注入的目的。如何在PHP中实现依赖注入?依赖注入在现在的编程中有着更加突出的优势,这也是ThinkPHP、Laravel等框架采用这种编程思想的原因。那么这些框架是如何使用PHP来实现的呢?让我们用一个简单的案例来解释其中的奥秘。首先,我们创建一个类,看起来是这样的,包括一个属性和两方:假设我们现在还有另外两个类,redisDB和cache,redisDB提供了对redis数据库的操作,cache负责缓存功能的实现和依赖在redisDB上。如下:在上面的类中,我们简单的实现了redis的查询、存储和删除。另一个类和现在的类结构非常相似:现在我们已经实现了redisDB和cache这两个组件。具体细节这里不讨论。让我们看看如何使用它。首先,你需要在容器中注入两个组件:你可能会觉得这有点麻烦。cache和redisDB的结构如此相似,redis是否可以不分开单独写进cache?但是大家有没有想过,有些数据不是那么及时,而且数量比较大,用redis有点不合适,mongodb是更好的选择;有些数据更新频率较慢,对查询速度没有要求,直接写入文件保存到硬盘可能更合适;或者,你的客户觉得redis运维有点难,你可以把他换成memcache。。。所以就分开了。然后,继续完善代码:我们新增了一个接口BackendInterface,规定了redisDB、mongoDB、file这三个类必须实现这个接口需要的功能。至于其他锦上添花的功能,就看你自己玩了。缓存的代码好像没有变,因为缓存不需要关心数据在数据库或文件中是如何存储的。缓存的调用者不需要关心缓存是如何实现的,只要根据接口实现相应的方法即可。您将从多人协作中获益更多。你只需要约定好接口,单独实现即可。上面的代码可以继续改进,直到你认为无可挑剔为止。比如redis服务可能在一次请求中调用多次,每次调用都会重新创建,这样会损害性能。只是扩展DI容器添加一个参数或添加一个方法,由你决定。这样,如果一个服务需要在一次请求中多次调用,可以将shared属性设置为true,减少不必要的浪费。如果你觉得每次注入都setDi有点麻烦,又想让它自动setDi,你可以这样做:那么,你可以这样做:我们实现的DI容器还是很简单的,不支持复杂的注射。你可以继续完善它。然而,通过这段代码你已经知道什么是依赖注入,你可以将这个想法应用到你的项目中,或者开始开发你自己的框架。