问答 / 3 / 9 / 创建于 1年前
容器绑定或者宏一般都写到服务提供者中,就算某些请求用不到也会加载,这样会不会浪费资源?
考虑到资源的开销,这就是你为什么看到大部分绑定都是通过闭包来来实现,比如:
$this->app->singleton(RuleService::class, function () { return new RuleService(); });
或者:
$this->app->bind(CryptTaskService::class, function () { return config('user.mobile.is_crypt') ? new EncryptService() : new DecryptService(); });
闭包只会在调用该服务的时候才会执行,这避免了一开始就实例化造成的开销。
当然,框架也允许你直接绑定实例来满足一些特殊需求。
宏的话我没理解楼主的意思,宏本身就是一段命名好的逻辑,你不去调用它本身也不会执行。
都用上laravel了, 还在乎浪费资源吗? :joy:
你可以在头信息加信息啊,服务启动判断下就行了
没办法,不过服务提供者是可以被缓存的,也可以设置延迟加载 DeferrableProvider 服务提供者《Laravel 10 中文文档》
DeferrableProvider
宏的话,如果在延迟加载的服务提供者中,也是延迟执行的
所以我基本不用服务提供者,因为我觉得没有必要,我就使用最普通的 new 对象。当然特别常用的服务除外。比如短信,支付等三方的接口。
延遲加載+閉包綁定
使用闭包绑定是不会主动加载的,只有你第一次用到的时候,执行了闭包函数才会加载。参见:www.php.net/manual/zh/functions.an...
看了楼上的一些评论,其实框架仅提供了服务注册的能力,并非一定要使用该能力。但想要使用服务注册,首先需要了解注册的目的。
当你向注册对象通过字符串绑定一个闭包、类型或实例的时候,就意味着它是可替换的。举个不太恰当的例子,就好比我们如果这样替换框架提供的模型类为自己的模型:
app()->bind(Illuminate\Database\Eloquent\Model::class,YourCustomeModel::class);
而能够这样写的前提是:
Illuminate\Database\Eloquent\Model::class
new
我们在使用三方包时的经验是,但凡是通过依赖注入(有可能不是框架提供的)进行管理的,都很容易做定制化,否则将异常困难,有的还要重复大量已经被三方包实现过的代码。
其实我们在框架中使用依赖注入的时候,完全不需要将所有要注入的服务在服务提供者中进行绑定,进需要在容器方法参数中声明即可。比如:
/** * 工作流步骤保存事件监听器 */ class WorkflowStepSavingListener { /** * Create the event listener. * * @param ValidateWorkflowStepService $service 工作流步骤验证服务 */ public function __construct( readonly public ValidateWorkflowStepService $service ) { } // ... }
以上代码中的 ValidateWorkflowStepService 类并没有在服务提供这种注册但依然会实例化默认的同名类型,这就好办了,如果我们想在某个场景下替换它,到时候再向服务提供者中添加相应的绑定规则即可:
ValidateWorkflowStepService
$this->app->bind(ValidateWorkflowStepService::class, function () { if ('testing' === config('app.env')) { return new YourStrictValidateService(); } });
关于依赖注入还有更多骚操作这里就不再一一展开。虽然有些跑题,但我想表达的是,项目代码随着需求的变动和演进,会保持向庞杂和混乱发展的趋势,对抗这一趋势的方法往往会在项目初期耗费一些开发学习成本和运行成本,但随着项目的展开,你可能会发现这些付出都是值得的。
我要举报该,理由是:
高认可度评论:
考虑到资源的开销,这就是你为什么看到大部分绑定都是通过闭包来来实现,比如:
或者:
闭包只会在调用该服务的时候才会执行,这避免了一开始就实例化造成的开销。
当然,框架也允许你直接绑定实例来满足一些特殊需求。
宏的话我没理解楼主的意思,宏本身就是一段命名好的逻辑,你不去调用它本身也不会执行。
都用上laravel了, 还在乎浪费资源吗? :joy:
你可以在头信息加信息啊,服务启动判断下就行了
考虑到资源的开销,这就是你为什么看到大部分绑定都是通过闭包来来实现,比如:
或者:
闭包只会在调用该服务的时候才会执行,这避免了一开始就实例化造成的开销。
当然,框架也允许你直接绑定实例来满足一些特殊需求。
宏的话我没理解楼主的意思,宏本身就是一段命名好的逻辑,你不去调用它本身也不会执行。
没办法,不过服务提供者是可以被缓存的,也可以设置延迟加载
DeferrableProvider
服务提供者《Laravel 10 中文文档》宏的话,如果在延迟加载的服务提供者中,也是延迟执行的
所以我基本不用服务提供者,因为我觉得没有必要,我就使用最普通的 new 对象。当然特别常用的服务除外。比如短信,支付等三方的接口。
延遲加載+閉包綁定
使用闭包绑定是不会主动加载的,只有你第一次用到的时候,执行了闭包函数才会加载。参见:www.php.net/manual/zh/functions.an...
看了楼上的一些评论,其实框架仅提供了服务注册的能力,并非一定要使用该能力。但想要使用服务注册,首先需要了解注册的目的。
目的一:解耦合
当你向注册对象通过字符串绑定一个闭包、类型或实例的时候,就意味着它是可替换的。举个不太恰当的例子,就好比我们如果这样替换框架提供的模型类为自己的模型:
而能够这样写的前提是:
Illuminate\Database\Eloquent\Model::class
模型的实例化;new
来实例化。我们在使用三方包时的经验是,但凡是通过依赖注入(有可能不是框架提供的)进行管理的,都很容易做定制化,否则将异常困难,有的还要重复大量已经被三方包实现过的代码。
目的二:便捷
其实我们在框架中使用依赖注入的时候,完全不需要将所有要注入的服务在服务提供者中进行绑定,进需要在容器方法参数中声明即可。比如:
以上代码中的
ValidateWorkflowStepService
类并没有在服务提供这种注册但依然会实例化默认的同名类型,这就好办了,如果我们想在某个场景下替换它,到时候再向服务提供者中添加相应的绑定规则即可:快速总结一下
关于依赖注入还有更多骚操作这里就不再一一展开。虽然有些跑题,但我想表达的是,项目代码随着需求的变动和演进,会保持向庞杂和混乱发展的趋势,对抗这一趋势的方法往往会在项目初期耗费一些开发学习成本和运行成本,但随着项目的展开,你可能会发现这些付出都是值得的。