本文目录导读:

我来详细讲解PHP依赖注入容器(DIC)的自动解析机制,包括完整实现和最佳实践。
基础依赖注入容器实现
基础容器类
<?php
namespace App\Container;
class Container
{
/**
* 已注册的服务实例
*/
private array $instances = [];
/**
* 已注册的服务定义(闭包)
*/
private array $definitions = [];
/**
* 别名映射
*/
private array $aliases = [];
/**
* 实例化中的类(用于检测循环依赖)
*/
private array $resolving = [];
/**
* 绑定接口到实现
*/
public function bind(string $abstract, $concrete = null): void
{
if ($concrete === null) {
$concrete = $abstract;
}
if ($concrete instanceof \Closure) {
$this->definitions[$abstract] = $concrete;
} else {
// 存储类名,延迟实例化
$this->definitions[$abstract] = function () use ($concrete) {
return $this->build($concrete);
};
}
}
/**
* 绑定单例
*/
public function singleton(string $abstract, $concrete = null): void
{
$this->bind($abstract, $concrete);
// 标记为单例
$this->definitions[$abstract] = function () use ($abstract) {
if (!isset($this->instances[$abstract])) {
$this->instances[$abstract] = call_user_func($this->definitions[$abstract], $this);
}
return $this->instances[$abstract];
};
}
/**
* 设置实例
*/
public function instance(string $abstract, $instance): void
{
$this->instances[$abstract] = $instance;
}
/**
* 添加别名
*/
public function alias(string $abstract, string $alias): void
{
$this->aliases[$alias] = $abstract;
}
/**
* 从容器中解析服务
*/
public function make(string $abstract)
{
// 解析别名
$abstract = $this->getAlias($abstract);
// 如果已有实例,直接返回
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
// 检测循环依赖
if (isset($this->resolving[$abstract])) {
throw new \RuntimeException("Circular dependency detected: {$abstract}");
}
$this->resolving[$abstract] = true;
try {
// 如果有定义,使用定义创建
if (isset($this->definitions[$abstract])) {
$object = call_user_func($this->definitions[$abstract], $this);
} else {
// 否则自动解析
$object = $this->build($abstract);
}
} finally {
unset($this->resolving[$abstract]);
}
return $object;
}
/**
* 自动构建类
*/
public function build(string $class)
{
// 通过反射获取类信息
$reflector = new \ReflectionClass($class);
// 检查类是否可实例化
if (!$reflector->isInstantiable()) {
throw new \Exception("Class {$class} is not instantiable");
}
// 获取构造函数
$constructor = $reflector->getConstructor();
// 没有构造函数,直接实例化
if (is_null($constructor)) {
return new $class();
}
// 获取构造函数的参数
$dependencies = $this->resolveDependencies($constructor->getParameters());
// 创建类实例
return $reflector->newInstanceArgs($dependencies);
}
/**
* 解析构造函数依赖
*/
private function resolveDependencies(array $parameters): array
{
$dependencies = [];
foreach ($parameters as $parameter) {
$dependency = $this->resolveParameter($parameter);
if ($dependency !== null) {
$dependencies[] = $dependency;
}
}
return $dependencies;
}
/**
* 解析单个参数
*/
private function resolveParameter(\ReflectionParameter $parameter)
{
// 获取参数类型
$type = $parameter->getType();
if ($type && !$type->isBuiltin()) {
// 类型是类,从容器中解析
$typeName = $type->getName();
return $this->make($typeName);
}
// 参数有默认值
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
}
// 尝试使用参数名查找配置
if (isset($this->config[$parameter->getName()])) {
return $this->config[$parameter->getName()];
}
throw new \Exception("Unable to resolve parameter: {$parameter->getName()}");
}
/**
* 解析别名
*/
private function getAlias(string $abstract): string
{
return $this->aliases[$abstract] ?? $abstract;
}
}
增强版容器(支持更多特性)
<?php
namespace App\Container;
use ReflectionClass;
use ReflectionMethod;
use ReflectionParameter;
class AdvancedContainer extends Container
{
/**
* 已解析的服务标记
*/
private array $shared = [];
/**
* 参数默认值配置
*/
private array $parameterOverrides = [];
/**
* 服务修饰器
*/
private array $decorators = [];
/**
* 方法调用注入
*/
public function call($callable, array $parameters = [])
{
if (is_string($callable) && strpos($callable, '@') !== false) {
[$class, $method] = explode('@', $callable);
$instance = $this->make($class);
$callable = [$instance, $method];
}
if (is_array($callable)) {
$reflection = new ReflectionMethod($callable[0], $callable[1]);
} elseif (is_object($callable) && !$callable instanceof \Closure) {
$reflection = new ReflectionMethod($callable, '__invoke');
} else {
$reflection = new \ReflectionFunction($callable);
}
return $reflection->invokeArgs($this->resolveDependenciesForMethod($reflection, $parameters));
}
/**
* 解析方法依赖
*/
private function resolveDependenciesForMethod($reflection, array $parameters = []): array
{
$dependencies = [];
foreach ($reflection->getParameters() as $parameter) {
// 优先使用传入的参数
if (array_key_exists($parameter->getName(), $parameters)) {
$dependencies[] = $parameters[$parameter->getName()];
continue;
}
// 解析类型依赖
$dependency = $this->resolveParameter($parameter);
if ($dependency !== null) {
$dependencies[] = $dependency;
}
}
return $dependencies;
}
/**
* 添加服务修饰器
*/
public function extend(string $abstract, callable $decorator): void
{
$this->decorators[$abstract][] = $decorator;
}
/**
* 重写make方法以支持修饰器
*/
public function make(string $abstract)
{
$instance = parent::make($abstract);
if (isset($this->decorators[$abstract])) {
foreach ($this->decorators[$abstract] as $decorator) {
$instance = $decorator($instance, $this);
}
}
return $instance;
}
/**
* 设置参数覆盖
*/
public function when(string $class): ParameterOverrider
{
return new ParameterOverrider($class, $this);
}
/**
* 自动解析类并调用方法
*/
public function resolveAndCall(string $class, string $method, array $parameters = [])
{
$instance = $this->make($class);
$reflection = new ReflectionMethod($instance, $method);
return $reflection->invokeArgs(
$this->resolveDependencies($reflection->getParameters(), $parameters)
);
}
/**
* 获取所有已注册的服务
*/
public function getRegisteredServices(): array
{
return array_keys($this->definitions);
}
}
/**
* 参数覆盖器辅助类
*/
class ParameterOverrider
{
private string $class;
private AdvancedContainer $container;
private array $overrides = [];
public function __construct(string $class, AdvancedContainer $container)
{
$this->class = $class;
$this->container = $container;
}
public function needs(string $parameter): self
{
$this->overrides['current'] = $parameter;
return $this;
}
public function give($value): void
{
// 实现参数覆盖逻辑
$this->container->addParameterOverride(
$this->class,
$this->overrides['current'],
$value
);
}
}
实际使用示例
<?php
// 定义接口和类
interface MailerInterface
{
public function send(string $to, string $message): bool;
}
class SmtpMailer implements MailerInterface
{
public function __construct(
private string $host,
private int $port = 587,
private string $username = '',
private string $password = ''
) {}
public function send(string $to, string $message): bool
{
echo "Sending email to {$to} via SMTP\n";
return true;
}
}
class UserService
{
public function __construct(
protected UserRepository $userRepository,
protected MailerInterface $mailer,
protected LoggerInterface $logger
) {}
public function registerUser(array $data): User
{
$user = $this->userRepository->create($data);
$this->mailer->send($user->email, 'Welcome!');
$this->logger->info("User {$user->id} registered");
return $user;
}
}
class UserRepository
{
public function __construct(
protected DatabaseConnection $db
) {}
public function create(array $data): User
{
return new User($data['id'] ?? 1, $data['email']);
}
}
class DatabaseConnection
{
public function __construct(
private string $dsn,
private bool $persistent = true
) {}
}
class LoggerInterface {}
class FileLogger extends LoggerInterface {}
// 使用容器
$container = new AdvancedContainer();
// 配置基础服务
$container->bind('database.config', [
'dsn' => 'mysql:host=localhost;dbname=app',
'persistent' => true
]);
// 绑定具体类
$container->bind(DatabaseConnection::class, function ($c) {
$config = $c->make('database.config');
return new DatabaseConnection($config['dsn'], $config['persistent']);
});
$container->bind(LoggerInterface::class, FileLogger::class);
$container->singleton(MailerInterface::class, SmtpMailer::class);
// 自动解析(无需手动注册 UserService)
try {
$userService = $container->make(UserService::class);
$user = $userService->registerUser([
'id' => 1,
'email' => 'user@example.com'
]);
echo "User created: {$user->email}\n";
} catch (Exception $e) {
echo "Error: {$e->getMessage()}\n";
}
// 方法调用注入
$result = $container->call(function (UserRepository $repo, MailerInterface $mailer) {
return $repo->findAll();
});
// 使用别名
$container->alias('user.service', UserService::class);
$service = $container->make('user.service');
专业级完整实现
<?php
namespace App\Container;
use ReflectionClass;
use ReflectionParameter;
use Throwable;
interface ContainerInterface
{
public function get(string $id);
public function has(string $id): bool;
}
class AutoWireContainer implements ContainerInterface
{
use HasParameterOverrides;
use HasAliases;
private array $bindings = [];
private array $instances = [];
private array $contextual = [];
private array $resolving = [];
private array $buildStack = [];
/**
* 自动解析并缓存结果
*/
public function get(string $id)
{
$id = $this->resolveAlias($id);
// 检测循环依赖
if (isset($this->buildStack[$id])) {
throw new CircularDependencyException(
"Circular dependency detected: " . implode(' -> ', array_keys($this->buildStack))
);
}
// 从实例缓存获取
if (isset($this->instances[$id])) {
return $this->instances[$id];
}
$this->buildStack[$id] = true;
try {
$instance = $this->resolve($id);
// 单例缓存
if ($this->isShared($id)) {
$this->instances[$id] = $instance;
}
return $instance;
} finally {
unset($this->buildStack[$id]);
}
}
/**
* 核心解析逻辑
*/
protected function resolve(string $concrete)
{
// 查找绑定
if (isset($this->bindings[$concrete])) {
$binding = $this->bindings[$concrete];
if ($binding instanceof \Closure) {
return $binding($this);
}
$concrete = $binding;
}
// 上下文绑定解析
$contextualBindings = $this->getContextualBindings();
if (isset($contextualBindings[$concrete])) {
$concrete = $contextualBindings[$concrete];
}
return $this->buildClass($concrete);
}
/**
* 通过反射构建类
*/
protected function buildClass(string $class)
{
try {
$reflector = new ReflectionClass($class);
} catch (Throwable $e) {
throw new BindingResolutionException("Target class [$class] does not exist", 0, $e);
}
if (!$reflector->isInstantiable()) {
throw new BindingResolutionException(
"Target [$class] is not instantiable"
);
}
// 获取构造函数
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
return new $class();
}
// 解析依赖参数
$dependencies = $this->resolveDependencies(
$constructor->getParameters()
);
// 创建实例并执行属性注入
$instance = $reflector->newInstanceArgs($dependencies);
return $this->performPropertyInjection($instance;
}
/**
* 解析构造函数依赖
*/
protected function resolveDependencies(array $parameters): array
{
$dependencies = [];
foreach ($parameters as $parameter) {
if ($this->hasParameterOverride($parameter)) {
$dependencies[] = $this->resolveParameterOverride($parameter);
continue;
}
$dependency = $this->resolveClassDependency($parameter);
if ($dependency !== null) {
$dependencies[] = $dependency;
}
}
return $dependencies;
}
/**
* 解析类类型依赖
*/
protected function resolveClassDependency(ReflectionParameter $parameter)
{
$type = $parameter->getType();
// 检查是否为类类型
if ($type && !$type->isBuiltin()) {
$typeName = $type->getName();
// 检查是否实现接口
if ($type->isInterface()) {
return $this->resolveInterface($typeName);
}
return $this->get($typeName);
}
// 检查默认值
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
}
// 检查是否可空
if ($type && $type->allowsNull()) {
return null;
}
throw new UnresolvableDependencyException(
"Unable to resolve dependency [{$parameter->getName()}] for parameter"
);
}
/**
* 解析接口实现
*/
protected function resolveInterface(string $interface): mixed
{
if (isset($this->bindings[$interface])) {
return $this->get($interface);
}
// 尝试找到实现类
$implementations = $this->findImplementations($interface);
if (count($implementations) === 1) {
return $this->get($implementations[0]);
}
if (count($implementations) > 1) {
throw new AmbiguousBindingException(
"Multiple implementations found for interface: {$interface}"
);
}
throw new BindingResolutionException(
"No concrete implementation found for interface: {$interface}"
);
}
/**
* 查找接口的类实现
*/
protected function findImplementations(string $interface): array
{
// 这里可以搜索项目目录或使用已有的映射
// 简单实现 - 从已注册的绑定中查找
$implementations = [];
foreach ($this->bindings as $key => $binding) {
if (is_string($binding) && class_exists($binding)) {
$reflection = new ReflectionClass($binding);
if ($reflection->implementsInterface($interface)) {
$implementations[] = $binding;
}
}
}
return $implementations;
}
/**
* 属性注入
*/
protected function performPropertyInjection($instance)
{
$reflection = new ReflectionClass($instance);
foreach ($reflection->getProperties() as $property) {
// 检查属性的注入注解(这里简单演示)
if ($property->getAttributes(Inject::class)) {
$property->setAccessible(true);
$type = $property->getType();
if ($type && !$type->isBuiltin()) {
$property->setValue(
$instance,
$this->get($type->getName())
);
}
}
}
return $instance;
}
public function has(string $id): bool
{
return isset($this->bindings[$id]) ||
isset($this->instances[$id]) ||
class_exists($id);
}
/**
* 清除容器缓存
*/
public function flush(): void
{
$this->instances = [];
$this->resolving = [];
}
}
// 自定义异常类
class CircularDependencyException extends \RuntimeException {}
class BindingResolutionException extends \RuntimeException {}
class UnresolvableDependencyException extends \RuntimeException {}
class AmbiguousBindingException extends \RuntimeException {}
使用第三方容器(推荐)
Composer PHP-DI
<?php
use DI\ContainerBuilder;
$containerBuilder = new ContainerBuilder();
$containerBuilder->useAutowiring(true);
$containerBuilder->useAnnotations(true);
// 配置定义
$containerBuilder->addDefinitions([
'database.host' => 'localhost',
DatabaseConnection::class => function ($c) {
return new DatabaseConnection(
"mysql:host={$c->get('database.host')};dbname=app"
);
},
MailerInterface::class => DI\autowire(SmtpMailer::class),
UserService::class => DI\create()
->constructor(
DI\get(UserRepository::class),
DI\get(MailerInterface::class),
DI\get(LoggerInterface::class)
),
]);
$container = $containerBuilder->build();
// 自动解析
$userService = $container->get(UserService::class);
// 使用注解注入
class OrderService
{
/**
* @Inject
* @var PaymentGatewayInterface
*/
private $paymentGateway;
/**
* @Inject
* @var OrderRepository
*/
private OrderRepository $repository;
public function process(Order $order)
{
return $this->paymentGateway->charge($order->amount);
}
}
Laravel容器的自动注入
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\UserService;
class UserController extends Controller
{
public function register(
Request $request,
UserService $userService // 自动注入
) {
// 使用自动注入的服务
$user = $userService->register($request->all());
return response()->json($user);
}
}
性能优化和最佳实践
自动解析缓存
<?php
class CacheableContainer extends AdvancedContainer
{
private $cache;
public function __construct(CacheInterface $cache = null)
{
parent::__construct();
$this->cache = $cache ?? new ArrayCache();
}
public function make(string $abstract)
{
$cacheKey = "container.{$abstract}";
// 使用缓存
if ($this->cache->has($cacheKey)) {
return $this->cache->get($cacheKey);
}
$instance = parent::make($abstract);
// 缓存结果
if ($this->shouldCache($abstract)) {
$this->cache->set($cacheKey, $instance);
}
return $instance;
}
}
- 接口绑定优先:优先绑定接口到具体实现
- 延迟加载:不要立即实例化所有服务
- 合理使用单例:只对真正需要保持状态的服务使用单例
- 避免循环依赖:通过构造函数注入减少循环依赖
- 容器配置集中:将容器配置集中在一个文件中管理
- 性能优化:对不经常变化的服务使用缓存
// 典型应用配置
return [
Registration::class => Registration::class,
MailerInterface::class => create(SmtpMailer::class),
'services.names' => [
'PHP',
'Laravel',
'Node.js'
],
'services.paths' => function ($container) {
return $container->get('services.names');
}
];
这样的自动解析机制让开发者能够专注于业务逻辑,而不用关心对象如何创建和依赖如何管理。