看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 关注
- 799 浏览
添加回答
举报
0/150
提交
取消