thinkphp6的中阶教程

依赖注入 和 控制反转

其实 依赖注入 和 控制反转 说的是同一件事情,只是站的角度不同而已。
我们就拿超人和小怪兽的事情来做类比对象。

地球受到了威胁,不断有小怪兽来想要破坏地球,每来一个小怪兽我们就需要找一个超人去对付他,一个超人肯定是不够的,因为每次来到小怪兽都是不一样的,他们所具有的能力也是不一样的。

因此我们必须找到合适的超人去对付他,最坏的情况是每来一个小怪兽我们就要找一个或者制造一个新超人,那么来十个小怪兽,我们就要制造十个,来百个就要制造百个,来千,来万,来亿我们就要制造相应的超人,而大部分超人只能用一次。

为了解决这个问题我们引入依赖注入和控制反转的概念,我们将超人和超能力分开,独立的超人和独立的超能力,当一个小怪兽来的时候我们找到超人,将相应的超能力给予他,让他去消灭小怪兽。

这样的话我们只需要几个超人就好了,我们不再需要制造超人,而是研究如何制造更多更好的超能力给超人使用。

超能力和超人不再是强依赖关系。超能力是由外部给予超人的,超人和超能力有依赖,但是这个依赖是外部给予,因此我们可以说超能力是由外部注入给他的,所以这就叫 依赖注入。

而反过来说,超人具有何种超能力不是他内部自身控制的,而是由外部控制的,相当于将超能力具有何种功效交给了外部,外部来决定超人该有的超能力,所以超能力的控制权被由自身控制反转为外部控制,这被称为 控制反转。

这就是关于 依赖注入 和 控制反转 的我的比较好理解的解释。它能较好的解决对象与对象之间的强耦合问题,同时也能做的按需使用按需加载。


实例:Class A 中用到了 Class B 的对象 b,一般情况下,需要在 A 的代码中显式的 new 一个 B 的对象。
采用依赖注入技术之后,A 的代码只需要定义一个私有的 B 对象,不需要直接 new 来获得这个对象,而是通过相关的容器控制程序来将 B 对象在外部 new 出来并注入到 A 类里的引用中。

这样做有什么好处呢?
解释:假如现在有 N 多个类,需要用到 Class B, 那就需要在类里面实例化 N 多次,这样对于后期的维护和管理都是不方便的,如果后期需求发生改变,那更改量有大很多。

依赖注入的具体实现:

image.png

上面代码中的就是依赖注入,现在又有一个问题
假如,现在类 b 中的 b 方法现在改名为 c 了,那 a 类里面的 a 方法中,就要将 b 类中调用的 b 方法改成 c 方法。那依旧涉及到那个问题,如果有 N 多个类要用到 B 类呢?那需要做的也是去 N 多个类中不断得去改,这样对后期得维护,需求更改都是要花费很大的成本。

直接贴代码:


image.png

图中可以看到,b 类是一个接口类,c,d 继承了 b 类,接口类的具体规则。
如果将C类中是b()改为c(),那编辑器会提示错误,由于接口必须有b函数,所以再写一个b函数即可。


TP6中 自动进行依赖注入

namespace app\controller;
class Foo 
{
    public function __construct(Bar $bar)
    {
    }
}

如果直接new的话,需要手动传入Bar对象实例

$bar = new Bar(); 
$foo = new Foo($bar);

如果使用invoke的话,可以自动进行依赖注入。

$foo = invoke('app\controller\Foo'); //不需要先new Bar,是自动进行依赖注入

容器

一个基本的服务容器
先搞清楚服务的概念,不要想多了,任何一个功能,任务都可以叫做服务 service。所以说功能类对象,就是服务。
再看容器,把这些服务装在一起,装在哪?就是一个容器。其实就是一个可以找到这些服务的一个对象。

通常一个容器要具有绑定和解析两个操作。

绑定,指的是将获取服务对象的方法在容器中进行注册。相当于将服务装入到了容器中。
解析,指的是将绑定到容器中的服务从容器中提取出来,注意通常我们绑定的不是对象本身,而是生成对象的代码,因此解析时通常是执行代码来得到对象。

# 1, 服务容器定义
/**
 * Class Application
 * 服务容器类,类名参考Laravel
 */
class Application
{
//    已绑定(注册)的服务
    private $services = [];

    /**
     * 绑定(注册)
     * @param $class string
     * @param $generator Closure
     */
    public function bind($class, $generator)
    {
        $this->services[$class] = $generator;
    }

    /**
     * 解析
     * @param $class string
     */
    public function make($class)
    {
        //return $this->services[$class]; //这样返回的是函数,不是函数结果
        return call_user_func($this->services[$class]); //这样是运行函数,返回函数结果
    }
}

# 2, 服务类示例
/**
 * Class Kernel
 * 内核服务类
 */
class Kernel
{
}
/**
 * Class Request
 * 请求服务类
 */
class Request
{
}

# 3, 绑定服务到容器,通常在程序初始化阶段完成
$app = new Application();
$app->bind('Kernel', function() {
    return new Kernel();
});
$app->bind('Request', function() {
    return new Request();
});

# 4, 需要时从容器中解析
$kernel = $app->make('Kernel');
var_dump($kernel);
$request = $app->make('Request');
var_dump($request);

观察上面的代码,Application 类就是服务容器类,实例化的 $app 就是服务容器对象。服务都绑定在这个容器上。
Kernel 和 Request 就是具体的某个服务。别忘了任何功能都可以是服务。
$app->bind (),就是将服务绑定到容器中,注意,绑定的是对象生成代码,而不是对象本身。因此绑定时,并没有去实例化对象。
$app->make (),就是从服务容器中解析服务,其实就是调用对应类的生成代码,得到对应的服务对象。

以上就是一个基本的服务容器。提供服务容器这种架构的目的,就是将项目中各种各样复杂多样,需要复用的功能整理到一起来管理。

什么情况适合放入容器

  • 容器中的类并不会自动执行,而是调用时执行
  • tp6容器中已经调用过的类会自动使用单例,所以这是容器的优势

适合放入容器,不放服务中:
工具类(方便、并且是单例)


TP6的服务

就是需要在控制器之前,先完成一些配置、操作等,可放入服务中。
因为服务的执行优先级高
1、会先执行 自定义服务类的 register() 方法 将服务绑定到容器中
2、再执行 自定义服务类的 boot() 启动方法,执行函数内的操作

适合放入服务:
微信、短信、上传、用户、管理员、配置信息等,放入容器


中间件

中间件主要用于拦截或过滤应用的HTTP请求,并进行必要的业务处理。

适合中间件:
用户、管理员、配置信息等从容器中调用对应的方法,自动单例

跟http请求相关的放 中间件,不相关的放 服务


请求顺序

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容