PHP依赖注入与服务容器深度剖析

发布时间:2026/6/1 4:23:12

PHP依赖注入与服务容器深度剖析 PHP依赖注入与服务容器深度剖析依赖注入是控制反转的一种实现方式。框架中的服务容器负责管理对象的创建和依赖关系。今天深入说说服务容器的实现原理。先回顾一下依赖注入的基本概念。传统的代码在类内部创建依赖导致紧耦合。依赖注入把依赖从外部传入实现松耦合。php// 没有依赖注入class OrderProcessor{private Logger $logger;public function __construct(){// 在内部创建依赖紧耦合$this-logger new FileLogger(/var/log/app.log);}}// 构造函数注入class OrderProcessorDI{public function __construct(private LoggerInterface $logger // 依赖从外部传入) {}}// 属性注入class OrderProcessorProperty{public LoggerInterface $logger; // 从外部设置}// Setter注入class OrderProcessorSetter{private LoggerInterface $logger;public function setLogger(LoggerInterface $logger): void{$this-logger $logger;}}?自动装配是容器的核心功能。通过反射分析类的构造函数递归解析所有依赖。phpclass Container{private array $bindings [];private array $instances [];private array $aliases [];public function bind(string $abstract, callable|string|null $concrete null, bool $shared false): void{if ($concrete null) {$concrete $abstract;}if (! $concrete instanceof Closure) {$concrete function (Container $container) use ($concrete) {return $container-build($concrete);};}$this-bindings[$abstract] compact(concrete, shared);}public function singleton(string $abstract, callable|string|null $concrete null): void{$this-bind($abstract, $concrete, true);}public function instance(string $abstract, object $instance): void{$this-instances[$abstract] $instance;}public function alias(string $abstract, string $alias): void{$this-aliases[$alias] $abstract;}public function make(string $abstract): mixed{$abstract $this-resolveAlias($abstract);if (isset($this-instances[$abstract])) {return $this-instances[$abstract];}if (!isset($this-bindings[$abstract])) {return $this-build($abstract);}$binding $this-bindings[$abstract];$object ($binding[concrete])($this);if ($binding[shared]) {$this-instances[$abstract] $object;}return $object;}public function call(callable|array $callable, array $parameters []): mixed{if (is_array($callable)) {$ref new ReflectionMethod($callable[0], $callable[1]);} else {$ref new ReflectionFunction($callable);}$args [];foreach ($ref-getParameters() as $param) {$name $param-getName();if (isset($parameters[$name])) {$args[] $parameters[$name];continue;}$type $param-getType();if ($type instanceof ReflectionNamedType !$type-isBuiltin()) {$args[] $this-make($type-getName());} elseif ($param-isDefaultValueAvailable()) {$args[] $param-getDefaultValue();} else {throw new RuntimeException(无法解析参数: $name);}}return $ref-invokeArgs($args);}public function build(string $class): object{if (!class_exists($class)) {throw new RuntimeException(无法构建: $class);}$ref new ReflectionClass($class);$constructor $ref-getConstructor();if ($constructor null) {return $ref-newInstance();}$dependencies [];foreach ($constructor-getParameters() as $param) {$type $param-getType();if ($type null) {if ($param-isDefaultValueAvailable()) {$dependencies[] $param-getDefaultValue();} else {throw new RuntimeException(无法解析参数: {$param-getName()});}} elseif ($type-isBuiltin()) {if ($param-isDefaultValueAvailable()) {$dependencies[] $param-getDefaultValue();} else {throw new RuntimeException(无法解析内置类型: {$param-getName()});}} else {$dependencies[] $this-make($type-getName());}}return $ref-newInstanceArgs($dependencies);}public function has(string $abstract): bool{$abstract $this-resolveAlias($abstract);return isset($this-bindings[$abstract])|| isset($this-instances[$abstract])|| class_exists($abstract);}private function resolveAlias(string $abstract): string{return $this-aliases[$abstract] ?? $abstract;}}?服务提供者模式把相关的绑定和初始化逻辑组织在一起是框架扩展的标准方式。phpinterface ServiceProvider{public function register(Container $container): void;public function boot(Container $container): void;}class CacheServiceProvider implements ServiceProvider{public function register(Container $container): void{$container-singleton(cache.redis, function () {$redis new Redis();$redis-connect(127.0.0.1, 6379);return $redis;});$container-bind(cache.file, function () {return new FileCache(/tmp/cache);});}public function boot(Container $container): void{$redis $container-make(cache.redis);$redis-ping();}}class App{private Container $container;private array $providers [];public function __construct(){$this-container new Container();}public function register(array $providers): void{foreach ($providers as $provider) {$instance new $provider();$instance-register($this-container);$this-providers[] $instance;}}public function boot(): void{foreach ($this-providers as $provider) {$provider-boot($this-container);}}public function make(string $abstract): mixed{return $this-container-make($abstract);}}$app new App();$app-register([CacheServiceProvider::class]);$app-boot();$redis $app-make(cache.redis);echo 应用启动完成\n;?依赖注入和服务容器是框架的核心基础设施。理解它们的实现原理可以更高效地使用框架在遇到问题时也能快速定位。不管是自己实现容器还是使用框架自带的容器核心思想都是一样的。

相关新闻