Laravel框架下容器Container 的依赖注入和反射应用
依赖注入,简单说是把类里头依赖的对象,置于类外头,即客户端调用处。相当于把类与类解耦。
一个简单的例子:
- class A {
- public function __construct() {
- // 这种实例化写法, A类的内部,依赖了B类 需要解耦
- $this->b = new B();
- }
- public function say(){
- $this->b->talk();
- }
- }
- class B{
- public function __construct() {
- }
- public function talk(){
- echo __METHOD__;
- }
- }
- $a = new A;
- $a->say();
A类依赖B类,耦合较重。
换一种写法:
- class A {
- public function __construct(B $b) {// B的实例化,放在客户端,当作构造参数传递过来
- $this->b = $b;
- }
- public function say(){
- $this->b->talk();
- }
- }
- class B{
- public function __construct() {
- }
- public function talk(){
- echo __METHOD__;
- }
- }
- $b = new B;// 在客户端实例化B
- $a = new A($b);// 构造器中传递
- $a->say();
这个代码,就相当于实例化B的步骤放在了A类的外部,从而实现解耦。这就是依赖注入的一种实现方式。
Laravel框架中,通过这种依赖注入的方式,再配合反射功能,实现功能。
比如在Laravel的容器类,Container.php(vendor/laravel/framework/src/illuminate/Container/Container.php)中
利用反射,实例化注入的类。
来一段代码:
- /**
- *
- * 依赖注入的思想,把外部依赖的类放在构造函数的参数里
- *
- * Laravel框架根据反射 搞定依赖
- */
- class Test{
- public function __construct(Para $p1, Parb $p2) {
- echo $p1->getInfo()," ",$p2->getInfo()," ";
- }
- function say(){
- echo __CLASS__;
- return;
- }
- }
- /**
- * Class Para
- * 参数A
- */
- class Para {
- function getInfo() {
- echo __CLASS__;
- }
- }
- /**
- * Class Parb
- * 参数B
- */
- class Parb {
- function getInfo(){
- echo __CLASS__;
- }
- }
- $obj = new Test(new Para(), new Parb());
- // ===================================================
- $reflector = new ReflectionClass($obj);// 对象 反射其类信息
- $constructor = $reflector->getConstructor();
- $dependencies = $constructor->getParameters();// 获取构造器下的参数信息
- $parArr = array();
- foreach ($dependencies as $depend){
- // $depend->getClass()->name 获取类名称 构造器参数是类
- $parArr[] = new ($depend->getClass()->name)();
- }
- $refNew = $reflector->newInstanceArgs($parArr);// Test 对象
- $refNew->say();
代码中,获取$obj反射后的类信息,再取其构造器中的依赖类,实例化这些依赖类,再传入Test类中。
这就是Laravel容器中实现的依赖注入和反射应用。
下边的代码有助于理解Laravel框架下的容器Container概念。参考自文章:https://www.insp.top/article/learn-laravel-container
- <?php
- interface SuperModuleInterface{
- public function activate(array $target);
- }
- class Superman
- {
- protected $module;
- /**
- * Superman constructor.
- * @param SuperModuleInterface $module
- * 通过构造器 注入依赖
- */
- public function __construct(SuperModuleInterface $module)
- {
- $this->module = $module;
- }
- public function show(array $target){
- $this->module->activate($target);
- }
- }
- class PowerA implements SuperModuleInterface
- {
- public function activate(array $target)
- {
- echo '<pre>'. __METHOD__;
- print_r(func_get_args());
- }
- }
- class PowerB implements SuperModuleInterface
- {
- public function activate(array $target)
- {
- echo '<pre>'. __METHOD__;
- print_r(func_get_args());
- }
- }
- class Container
- {
- protected $binds;
- protected $instances;
- /**
- * @param $abstract
- * @param $concrete
- * 把代词 绑定到容器里,为后续make
- */
- public function bind($abstract, $concrete)
- {
- if ($concrete instanceof Closure) {
- $this->binds[$abstract] = $concrete;
- } else {
- $this->instances[$abstract] = $concrete;
- }
- }
- /**
- * @param $abstract
- * @param array $parameters
- * @return mixed
- * 创建对象
- */
- public function make($abstract, $parameters = [])
- {
- if (isset($this->instances[$abstract])) {
- return $this->instances[$abstract];
- }
- // 把容器对象$this,放到参数数组第一个元素。为call_user_func_array使用
- array_unshift($parameters, $this);
- // 这里$this->binds[$abstract] 绑定的闭包函数, 执行函数参数是$parameters
- return call_user_func_array($this->binds[$abstract], $parameters);
- }
- }
- // 创建一个容器(后面称作超级工厂)
- $container = new Container;
- // 向该 超级工厂添加超能力模组的生产脚本
- $container->bind('powerA', function($container) {
- return new PowerA;
- });
- // 同上
- $container->bind('powerB', function($container) {
- return new PowerB;
- });
- // 向该 超级工厂添加超人的生产脚本
- $container->bind('superman', function($container, $moduleName) {
- return new Superman($container->make($moduleName));
- });
- echo "<pre>";
- // 开始启动生产
- $superman_1 = $container->make('superman', ['powerA']);
- $superman_1->show(['a' => 1]);
- $superman_2 = $container->make('superman', ['powerB']);
- $superman_2->show(['b' => 1]);
Laravel框架下容器Container 的依赖注入和反射应用的更多相关文章
- laravel框架中所用到的依赖注入
用Laravel开发前前后后有2个月左右了,之前一直写Java,就像找到Java和PHP之前的共同点,用Java的某些原理去理解PHP会发现还是有很多共通之处的.Java的依赖注入已经是一个很常见的概 ...
- [转载]Spring下IOC容器和DI(依赖注入) @Bean及@Autowired
Spring下IOC容器和DI(依赖注入) @Bean及@Autowired自动装配 bean是什么 bean在spring中可以理解为一个对象.理解这个对象需要换一种角度,即可将spring看做一门 ...
- Laravel框架下路由的使用(源码解析)
本篇文章给大家带来的内容是关于Laravel框架下路由的使用(源码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 我的解析文章并非深层次多领域的解析攻略.但是参考着开发文 ...
- 基于Laravel框架下使用守护进程supervisor实现定时任务(毫秒)
本篇文章给大家带来的内容是关于基于Laravel框架下使用守护进程supervisor实现定时任务(毫秒),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 公司需要实现X分钟内每隔Y秒 ...
- 如何把对象手动注入Spring容器并实现依赖注入
将对象注入到Spring容器并实现依赖注入 public class UserDao { @Resource AccountService accountService; public void pr ...
- 【框架学习与探究之依赖注入--Autofac】
声明 本文欢迎转载,原文地址:http://www.cnblogs.com/DjlNet/p/7603642.html 序 同样的又是一个双11如期而至,淘宝/天猫实时数据显示,开场3分钟总交易额突破 ...
- 解析Laravel框架下的Contracts契约
Contracts Laravel 的契约是一组定义框架提供的核心服务的接口, 例如我们在介绍用户认证的章节中到的用户看守器契约IllumninateContractsAuthGuard 和用户提供器 ...
- 初识Spring框架实现IOC和DI(依赖注入)
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的, IoC是 ...
- Spring:Spring-IOC容器、DI依赖注入简介
Spring容器到底是什么? 从概念上讲:Spring 容器是 Spring 框架的核心,是用来管理对象的.容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁. 从具象化 ...
随机推荐
- 使用yum安装不知道到底安装在什么文件夹
find /* >yum001 #记录之前的文件夹 find /* >yum002 #记录安装完成后的文件夹 diff yum001 yum002 >yum000 ...
- sysbench的框架实现介绍
sysbench是一个非常经典的综合性能测试工具,它支持CPU,IO,内存,尤其是数据库的性能测试.那它是怎么做到通用性的呢,总结一句话是大量运用了重载的方法. sysbench总体架构 sysben ...
- SQL优化总结之一
一.实践中如何优化mysql 1) SQL语句及索引的优化 2) 数据库表结构的优化 3) 系统配置的优化 4) 硬件优化 二.索引的底层实现原理和优化 2.1 底层实现 在DB2数据库中索引采用的是 ...
- 在ASP.NET MVC 项目中 使用 echarts 画统计图
echarts 官方地址:http://echarts.baidu.com/ 一.根据图中的数据怎么从数据库中获取并组装成对应格式: 从数据库中获取对应数据,然后在项目中引用Newtonsoft.Js ...
- 【WebAPI No.3】API的访问控制IdentityServer4
介绍: IdentityServer是一个OpenID Connect提供者 - 它实现了OpenID Connect和OAuth 2.0协议.是一种向客户发放安全令牌的软件. 官网给出的功能解释是: ...
- 解决基于IIS的.net core HttpWebRequest 连接特别慢
用的是HttpWebRequest 连接特别慢,查找原因发现 : 由 HttpWebRequest. Proxy 代理的原因导致 . 其实请求1秒就完成了,那15秒是用来等待默认proxy超时的…… ...
- react 插槽(Portals)
前言: 昨天刚看了插槽,以为可以解决我工作中遇到的问题,非常激动,我今天又仔细想了想,发现并不能解决... 不过还是记录一下插槽吧,加深印象,嗯,就酱. 插槽作用: 插槽即:ReactDOM.crea ...
- ssm基础搭建步骤
今天搭建新的项目环境,从网上找了些ssm的搭建步骤,终于找到了一位csdn的大佬,可以说写的特别详细,按照上面步骤搭建即可,为了方便日后参考,转载到本人博客,原文链接:https://blog.csd ...
- iOS----------常见宏定义
在我们日常的项目中,合理的使用宏定义,会大大减少我们的代码量,以及代码的可读性,为方便读者使用,总结如下: pragma mark - Application相关 ///=============== ...
- C#字符串倒置函数的代码
把内容过程比较常用的内容珍藏起来,下边内容内容是关于C#字符串倒置函数的内容. public static string Reverse(string ReverseString) { String ...