为了账号安全,请及时绑定邮箱和手机立即绑定

laravel中Container依赖注入,多次生成类实例

laravel中Container依赖注入,多次生成类实例

PHP
拉莫斯之舞 2019-03-18 15:28:25
看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:不知道为啥我上传图片一直失败。。。将就看文字吧)

查看完整回答
反对 回复 2019-03-18
  • 2 回答
  • 0 关注
  • 786 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信