看laravel中Comtroller發現,類依賴注入時,當我通過make創建對象時,發現依賴被創建了多份實例。
代碼如下:
<?php
namespace Tests\Unit;
use Illuminate\Container\Container;
use Tests\TestCase;
interface SessionStorage
{
public function get($key);
public function set($key, $value);
}
class FileSessionStorage implements SessionStorage
{
public function __construct()
{
echo "file init \n";
}
public function get($key)
{
// TODO: Implement get() method.
}
public function set($key, $value)
{
// TODO: Implement set() method.
}
}
class MySqlSessionStorage implements SessionStorage
{
public function __construct()
{
echo "mysql init \n";
}
public function get($key)
{
// TODO: Implement get() method.
}
public function set($key, $value)
{
// TODO: Implement set() method.
}
}
class SimpleAuth
{
protected $session;
public function __construct(SessionStorage $session)
{
$this->session = $session;
}
public function get()
{
$this->session->get(null);
}
}
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testBasicTest()
{
$container = Container::getInstance();
$container->bind( SessionStorage::class, MysqlSessionStorage::class );
$container->make(SimpleAuth::class);
echo "-\n";
$container->bind( SessionStorage::class, FileSessionStorage::class );
$container->make(SimpleAuth::class);
echo "-\n";
$container->bind( SessionStorage::class, MysqlSessionStorage::class );
$container->make(SimpleAuth::class);
}
}
代碼的輸出結果如下:
跟預期不同的地方:
第一次make操作的時候,通過構造函數的輸出,可以看出,依賴關系僅僅被實例化了一次
但后面再次調用bind,make發現構造函數被調用了兩次
mysql init
-
file init
file init
-
mysql init
mysql init
嘗試debug:在make函數中記錄調用的次數。:
public function make($abstract, array $parameters = [])
{
if (stripos($abstract, 'SessionStorage') !== false) {
echo "make plus \n";
}
return $this->resolve($abstract, $parameters);
}
=================== 輸出結果 =================
make plus
make plus
mysql init
-
make plus
make plus
file init
make plus
make plus
file init
-
make plus
make plus
mysql init
make plus
make plus
mysql init
怎么破?。?!
2 回答

繁星coding
TA貢獻1797條經驗 獲得超4個贊
跟一下源碼,能找到問題:
1、bind()調用時,會把bind的abstract放在bindings數組中;
2、make()調用時,其實調用resolve,如果是單例(singleton)就會在instances中,查到返回就是單例,直接bind的不是單例,所以每次調用會有切僅有一次構造函數調用;
3、但是為啥調用了多次,問題在于第二次bind()的時候,因為前面已經make()過(也就是resolve過),所以在bind()函數的最后,會調用rebound()函數,在rebound()函數中會實例化一個abstract用于調用rebound的回調;
4、所以,并不是第二次make()的時候調用了兩次實例化,而是第二次bind()一次,第二次make()一次;因為第二次bind的時候,會觸發rebound;
(PS:不知道為啥我上傳圖片一直失敗。。。將就看文字吧)
- 2 回答
- 0 關注
- 816 瀏覽
添加回答
舉報
0/150
提交
取消