Laravel底层解释:控制反转和依赖注入、IOC容器和反射
控制器必须使用一个类A,然后newA它,然后调用该类的对象。但是这个类实例化的时候,必须要传递一个类B的实例来改造对象,我们必须先创建new B,然后再传递它。这就是类之间的依赖关系。
我们在控制器方法中更新这个类,然后使用它,但是我们发现框架中很多类不需要你实例化,方法中直接有形参可以使用。基本上,框架的底层会更新类,然后将其传递给方法参数,以便您可以直接在方法中使用它。那么方法中原来由new类创建的实例对象在方法外就变成new了,之后再传递。进来吧,从这个方法来看,这是一种反转,也就是控制反转。如果你在方法之外查看它,我不需要你的新方法。我已将新的形式参数传递给该方法。你可以直接使用它,那么这个角度就是依赖注入。事实上,它们基本上是同一件事。
现在我们了解了概念,接下来我们来了解什么是IOC容器和反射。
首先,我们有几个类,它们之间存在依赖关系。看里面的构造方法就知道了。我们需要在控制器方法中使用这个类A,但是上面我们已经知道我们不需要在方法中使用new。太复杂了,更何况A类还有这么多层依赖。所以框架底层帮我们new了然后给我们用(控制反转、依赖注入);
/**
* @author zhaoruiqing
* @date 2022-
* @desc 我是类A的注释
*/
class A
{
//我是构造函数的注释
public function __construct(B $b)
{
$this->b = $b;
}
//我是getB的注释
public function getB()
{
$this->b->bMethod();
}
}
class B
{
public function __construct(C $c,D $d)
{
$this->c = $c;
$this->d = $d;
}
public function bMethod()
{
echo "我是B中的方法bMethod()";
}
}
class C{
public function __construct(){
}
public function cMethod(){
echo "我是C中的方法cMethod()";
}
}
class D{
public function __construct(){
}
public function dMethod(){
echo "我是D中的方法dMethod()";
}
}
框架中怎么样,帮我们new A,然后我们创建一个工厂类,帮助我们实例化方法中的类,然后供我们使用: 如下图,
创建一个IOC工厂类,在数组中实例化这些类,然后在使用时将其提供给我们(工厂单例模式)。这就是控制反转,有一个专门的ioc类帮助我们实例化对象,并且不需要我们实例化它们,但是上面的代码仍然存在问题。我们的A类存储依赖于B类,而B类又依赖于CD和其他类,所以虽然它帮助我们实例化它,但它仍然需要被重写。中间写依赖(注意上图中没有写,这里添加)。
这是否意味着我们所有的类都具有依赖关系?如果这个工厂类是新的,那么包装框架的人是否必须手动填充每个类的依赖项?
当然不是,这个IOC工厂类会用到PHP的反射。其实反射就是PHP提供的一组API,可以让我们获取类信息。例如,我有一个包含属性、方法、类名、注释和静态的类。我们采用反射的方式来传递。对于这个类的名称,可以通过调用response的get方法来获取对应的属性或者成员方法、构造函数,甚至注释。
也就是我们的IOC工厂类帮助我们实例化框架底层的类。当我们这样做时,我们不必考虑告诉哪个类依赖于哪个类。框架可以调用反射方法来获取对应的类。构造方法,然后得到这个类必须经过哪个类的实例,即知道这个类需要的依赖类。
以下几组方法是反射。直接A。
具体代码如下:
class Ioc
{
protected $instances = [];
public function __construct()
{
}
public function getInstance($abstract){
//获取类的反射信息,也就是类的所有信息
$reflector = new ReflectionClass($abstract);
// echo $reflector->getDocComment(); 获取类的注释信息
//获取反射类的构造函数信息
$constructor = $reflector->getConstructor();
//获取反射类的构造函数的参数
$dependencies = $constructor->getParameters();
if(!$dependencies){
return new $abstract();
}
foreach ($dependencies as $dependency) {
if(!is_null($dependency->getClass())){
$p[] = $this->make($dependency->getClass()->name);
//这里$p[0]是C的实例化对象,$p[1]是D的实例化对象
}
}
//创建一个类的新实例,给出的参数将传递到类的构造函数
return $reflector->newInstanceArgs($p);
}
public function make($abstract)
{
return $this->getInstance($abstract);
}
}
$ioc = new Ioc();
$a = $ioc->make('A');
$a->getB();
此时,我们就可以使用IOC类来实例化控制器外部的类了(控制反转)。实例化过程使用反射和递归,然后将其传递给方法参数。 (依赖注入),供用户使用。
Lavavel 将 ioc 工厂类称为 IOC 容器。因为类被实例化并存储在变量中,所以变量对应于这些类的容器。只要你掌握了要点,你就可以随心所欲地称呼它。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。