php ioc 实现
PHP IOC 实现方法
依赖注入容器(DIC)基础实现
创建一个简单的容器类,用于存储和解析依赖关系。通过绑定接口与实现类,容器自动解析依赖链。
class Container {
protected $bindings = [];
public function bind($abstract, $concrete) {
$this->bindings[$abstract] = $concrete;
}
public function make($abstract) {
if (!isset($this->bindings[$abstract])) {
throw new Exception("No binding found for {$abstract}");
}
$concrete = $this->bindings[$abstract];
return is_callable($concrete) ? $concrete($this) : $this->build($concrete);
}
protected function build($concrete) {
$reflector = new ReflectionClass($concrete);
if (!$reflector->isInstantiable()) {
throw new Exception("{$concrete} is not instantiable");
}
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
return new $concrete();
}
$dependencies = $this->resolveDependencies($constructor->getParameters());
return $reflector->newInstanceArgs($dependencies);
}
protected function resolveDependencies($parameters) {
return array_map(function($param) {
return $this->make($param->getClass()->name);
}, $parameters);
}
}
使用反射自动解析
通过PHP的ReflectionClass分析类的构造函数参数,递归实例化所有依赖对象。此方法无需手动绑定具体实现,但要求依赖关系明确可推断。
$container = new Container();
$service = $container->make(Service::class); // 自动解析Service及其所有依赖
接口绑定实现
将接口绑定到具体实现类,实现松耦合。修改实现类时只需调整绑定关系,不影响上层代码。
$container->bind(LoggerInterface::class, FileLogger::class);
$logger = $container->make(LoggerInterface::class); // 返回FileLogger实例
闭包工厂绑定
对于需要复杂初始化的对象,使用闭包延迟创建过程。闭包接收容器实例以便解析嵌套依赖。
$container->bind(Database::class, function($container) {
$config = $container->make(Config::class);
return new Database($config->get('db_uri'));
});
PSR-11兼容容器
实现Psr\Container\ContainerInterface接口,确保与其他遵循PSR标准的库兼容。需实现get()和has()方法。
class PsrContainer extends Container implements \Psr\Container\ContainerInterface {
public function get($id) {
return $this->make($id);
}
public function has($id) {
return isset($this->bindings[$id]);
}
}
实际应用示例
在MVC框架中集中管理控制器依赖,避免在控制器内部手动实例化服务。
$container->bind(UserController::class, function($container) {
return new UserController(
$container->make(UserRepository::class),
$container->make(Mailer::class)
);
});
$controller = $container->make(UserController::class);
性能优化建议
对已解析的依赖进行缓存,避免重复反射开销。可通过在容器内添加$instances数组存储单例对象实现。

protected $instances = [];
public function singleton($abstract, $concrete) {
$this->bind($abstract, function($container) use ($concrete) {
if (!isset($this->instances[$abstract])) {
$this->instances[$abstract] = $container->build($concrete);
}
return $this->instances[$abstract];
});
}






