java 's IoC容器-重新绑定抽象类型


Laravel's IoC Container - Rebinding Abstract Types

在Laravel的Container Illuminate'Container'Container方法中,我们看到这段代码:

    // If the abstract type was already resolved in this container we'll fire the
    // rebound listener so that any objects which have already gotten resolved
    // can have their copy of the object updated via the listener callbacks.
    if ($this->resolved($abstract)) {
        $this->rebound($abstract);
    }

它似乎允许重新绑定任何先前解析的抽象类型。在哪些用例中需要重新绑定抽象类型?在rebound方法中,我们看到,如果抽象类型确实先前已被解析,则运行所有的rebound回调函数。

    /**
 * Fire the "rebound" callbacks for the given abstract type.
 *
 * @param  string  $abstract
 * @return void
 */
protected function rebound($abstract)
{
    $instance = $this->make($abstract);
    foreach ($this->getReboundCallbacks($abstract) as $callback) {
        call_user_func($callback, $this, $instance);
    }
}

谁能给一个现实生活中的例子,在什么情况下你会重新绑定一个抽象类型,你需要调用什么类型的回调?

该机制允许您定义将来注册的任何实现应该如何初始化。

例如:假设您有一个基于配置文件连接到某些服务器的RPC客户端。您可能希望任何客户端代码都能够扩展您的client类并注册它们自己的实现,但不需要手动使用设置文件中的输入初始化客户端。(这里的"客户端代码"指的是使用你的库的任何代码,这里的"客户端"一词令人困惑。)

(我想在我的Laravel项目中做类似的事情,因为我想只定义一次我的配置(rpc.client)的路径,而不是每次我注册不同的客户端实现。我不希望应用程序的其余部分关心这些事情)。

示例实现:

class CommunicationsServiceProvider extends ServiceProvider
{
/**
 * Register the application services.
 *
 * @return void
 */
public function register()
{
    $this->app->singleton(ClientInterface::class, function(Application $app)
    {
        return null; // Required to trigger the rebinding event with the second bind.
    });
    $this->app->rebinding(ClientInterface::class, function(Application $app, $client)
    {
        $options = $app['config']->get('rpc.client');
        /** @var Client $client */
        $client->configure($options);
        return $client;
    });
    $this->app->singleton(ClientInterface::class, function(Application $app)
    {
        $client = new Client ([]); // We intentionally use empty array to demonstrate 
                                   // that the config will be properly injected anyway.
        return $client;
    });
    // Note that the callback in the binding() method will be called, so even though 
    // we initialize the new Client with empty set of settings (we provide the [] into
    // the constructor), it will be properly initialized by the rebinding() callback.

所以每次有人注册一个新的客户端实现(通过App::bind()等),rebinding()中定义的回调将在实例上被调用。

结论

我想知道的是,当它没有在Laravel文档中记录并且不是容器合同(Illuminate'Contracts'Container'Container接口)的一部分并且只是具体实现(Illuminate'Container'Container类)的一部分时,使用rebinding()方法是否是个好主意。

似乎对于相同的用例,您可以使用"适当的"(记录并存在于公共API中)resolving()方法,这将导致每次有人解析此绑定时都调用configure($options)方法(与此情况相反,它只在客户端注册时调用一次)。

来源

我在本教程中第一次注意到这个功能,但老实说,我没有从那里的例子中正确理解它,不得不自己试验它。

免责声明

请注意,我不是这方面的专家。但是我最近一直在研究Laravel的IoC和这个方法,所以我想我可能会提供一些见解。