在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和这个方法,所以我想我可能会提供一些见解。