本文目录导读:

我来详细讲解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');
}
];
这样的自动解析机制让开发者能够专注于业务逻辑,而不用关心对象如何创建和依赖如何管理。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播