容器绑定或者宏一般都写到服务提供者中,就算某些请求用不到也会加载,这样会不会浪费资源?

容器绑定或者宏一般都写到服务提供者中,就算某些请求用不到也会加载,这样会不会浪费资源?

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 9
sanders

考虑到资源的开销,这就是你为什么看到大部分绑定都是通过闭包来来实现,比如:

        $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();
        });

闭包只会在调用该服务的时候才会执行,这避免了一开始就实例化造成的开销。

当然,框架也允许你直接绑定实例来满足一些特殊需求。

宏的话我没理解楼主的意思,宏本身就是一段命名好的逻辑,你不去调用它本身也不会执行。

1年前 评论
fatrbaby 1年前

都用上laravel了, 还在乎浪费资源吗? :joy:

1年前 评论
JaguarJack

你可以在头信息加信息啊,服务启动判断下就行了

1年前 评论
sanders

考虑到资源的开销,这就是你为什么看到大部分绑定都是通过闭包来来实现,比如:

        $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();
        });

闭包只会在调用该服务的时候才会执行,这避免了一开始就实例化造成的开销。

当然,框架也允许你直接绑定实例来满足一些特殊需求。

宏的话我没理解楼主的意思,宏本身就是一段命名好的逻辑,你不去调用它本身也不会执行。

1年前 评论
fatrbaby 1年前

没办法,不过服务提供者是可以被缓存的,也可以设置延迟加载 DeferrableProvider 服务提供者《Laravel 10 中文文档》

宏的话,如果在延迟加载的服务提供者中,也是延迟执行的

1年前 评论

所以我基本不用服务提供者,因为我觉得没有必要,我就使用最普通的 new 对象。当然特别常用的服务除外。比如短信,支付等三方的接口。

1年前 评论

延遲加載+閉包綁定

1年前 评论
fatrbaby

使用闭包绑定是不会主动加载的,只有你第一次用到的时候,执行了闭包函数才会加载。参见:www.php.net/manual/zh/functions.an...

1年前 评论
sanders

看了楼上的一些评论,其实框架仅提供了服务注册的能力,并非一定要使用该能力。但想要使用服务注册,首先需要了解注册的目的。

目的一:解耦合

当你向注册对象通过字符串绑定一个闭包、类型或实例的时候,就意味着它是可替换的。举个不太恰当的例子,就好比我们如果这样替换框架提供的模型类为自己的模型:

app()->bind(Illuminate\Database\Eloquent\Model::class,YourCustomeModel::class);

而能够这样写的前提是:

  1. 框架本身就使用了依赖注入来提供 Illuminate\Database\Eloquent\Model::class 模型的实例化;
  2. 你在使用模型的时候都是通过依赖注入的方式,而非直接 new 来实例化。

我们在使用三方包时的经验是,但凡是通过依赖注入(有可能不是框架提供的)进行管理的,都很容易做定制化,否则将异常困难,有的还要重复大量已经被三方包实现过的代码。

目的二:便捷

其实我们在框架中使用依赖注入的时候,完全不需要将所有要注入的服务在服务提供者中进行绑定,进需要在容器方法参数中声明即可。比如:

/**
 * 工作流步骤保存事件监听器
 */
class WorkflowStepSavingListener
{
    /**
     * Create the event listener.
     *
     * @param ValidateWorkflowStepService $service 工作流步骤验证服务
     */
    public function __construct(
        readonly public ValidateWorkflowStepService $service
    )
    {
    }
// ...
}

以上代码中的 ValidateWorkflowStepService 类并没有在服务提供这种注册但依然会实例化默认的同名类型,这就好办了,如果我们想在某个场景下替换它,到时候再向服务提供者中添加相应的绑定规则即可:

$this->app->bind(ValidateWorkflowStepService::class, function () {
    if ('testing' === config('app.env')) {
        return new YourStrictValidateService();
   }
});

快速总结一下

关于依赖注入还有更多骚操作这里就不再一一展开。虽然有些跑题,但我想表达的是,项目代码随着需求的变动和演进,会保持向庞杂和混乱发展的趋势,对抗这一趋势的方法往往会在项目初期耗费一些开发学习成本和运行成本,但随着项目的展开,你可能会发现这些付出都是值得的。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!