容器(Service Container)
Laravel 的核心就是一个 IOC 容器,也称为服务容器,服务容器是管理类依赖和执行依赖注入的强大工具
依赖注入(Dependency Injection)
当依赖不由内部创建生产,而是由外部以参数或其他形式注入的,即是依赖注入(DI),依赖注入作为控制反转最常见的一种实现方式 依赖注入的实现方式一般有:
- 构造函数或者初始化方法注入,依赖对象通过参数注入,这是最常用的方式
- 属性注入,通过设置对象的成员或属性来注入
- 方法注入,通过调用对象方法来注入
<?php
class db
{
protected $db;
public function select()
{
echo '查询数据库';
}
}
class User
{
protected $db;
public function __construct(db $db)
{
$this->db = $db;
}
public function index() {
$this->db->select();
}
}
$db = new db();
$user = new User($db);
$user->index();
控制反转(Inversion Of Control)
假设 A 对象依赖 B 对象。即A类需要B类协助时完成某个功能事项时,传统的情况下是在A类内创建B类的实例,但在IOC这里,创建B类的工作不再由A类来完成,而是通过容器来实现对对象的创建、管理,从在A类内创建移到了外部,消除了A类对B类创建的控制,因此称为控制反转。
传统写法与DI写法区别:
<?php
interface db
{
public function select();
}
class MysqlDb implements db
{
public function select(){
echo 'MysqlDb select';
}
}
class MongoDb implements db
{
public function select()
{
echo 'MongoDb select';
}
}
class User
{
protected $db;
public function __construct()
{
$this->db = new MysqlDb();
}
public function select() {
$this->db->select();
}
}
$user = new User();
$user->select();
class DiUser
{
protected $db;
public function __construct(db $db)
{
$this->db = $db;
}
public function select() {
$this->db->select();
}
}
$user1 = new DiUser(new MysqlDb());
$user1->select();
$user2 = new DiUser(new MongoDb());
$user2->select();
一个简单的容器实例
原生构建IOC容器大致可以分为三大步骤来进行容器的构建。 1、绑定对象关系到容器的数组 2、通过反射拿到执行的类构造函数,拿到构造函数的参数 3、通过反射机制创建 操作对象
<?php
error_reporting(E_ALL);
ini_set('display_errors','On');
interface db
{
public function select();
}
class MysqlDb implements db
{
public function select(){
echo 'MysqlDb select';
}
}
class MongoDb implements db
{
public function select(){
echo 'MongoDb select';
}
}
class User
{
protected $db;
public function __construct(db $db)
{
$this->db = $db;
}
public function select() {
$this->db->select();
}
}
class Ioc
{
public $binding = [];
public function bind($abstract, $concrete) {
$this->binding[$abstract]['concrete'] = function ($ioc) use ($concrete) {
return $ioc->build($concrete);
};
}
public function make($abstract)
{
return $this->binding[$abstract]['concrete']($this);
}
public function build($concrete)
{
$reflector = new ReflectionClass($concrete);
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
return $reflector->newInstance();
}else {
$dependen = $constructor->getParameters();
$intances = $this->getDependencies($dependen);
return $reflector->newInstanceArgs($intances);
}
}
protected function getDependencies($dependen) {
$dependencies = [];
foreach ($dependen as $paramter){
$dependencies[] = $this->make($paramter->getClass()->name);
}
return $dependencies;
}
}
$ioc = new Ioc();
$ioc->bind('db','MysqlDb');
$ioc->bind('user','User');
$user = $ioc->make('user');
$user->select();
$ioc->bind('db','MongoDb');
$user = $ioc->make('user');
$user->select();
$ioc->bind('db','MysqlDb');
$user = $ioc->make('user');
$user->select();
|