Symfony 依赖注入容器详解
Symfony 的依赖注入容器是其最核心的组件之一,它实现了"控制反转"(IoC)设计模式。

基本概念
依赖注入:将对象的依赖关系从内部创建转移到外部注入
// 不好的做法 - 硬编码依赖
class UserController {
private $repository;
public function __construct() {
$this->repository = new UserRepository(); // 紧耦合
}
}
// 好的做法 - 依赖注入
class UserController {
private $repository;
public function __construct(UserRepository $repository) {
$this->repository = $repository; // 松耦合
}
}
服务容器核心服务
// 1. 注册服务(services.yaml)
services:
# 默认自动注册
App\Service\:
resource: '../src/Service/*'
autowire: true
autoconfigure: true
# 手动注册服务
App\Service\MailService:
arguments:
$mailer: '@Symfony\Component\Mailer\MailerInterface'
$adminEmail: 'admin@example.com'
# 注册接口实现
App\Repository\UserRepositoryInterface:
alias: App\Repository\DoctrineUserRepository
public: true
服务容器核心组件
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class CustomContainerConfiguration
{
public function configure()
{
$container = new ContainerBuilder();
// 1. 定义服务
$container->register('app.mailer', MailerService::class)
->setArguments([
new Reference('Symfony\Component\Mailer\MailerInterface'),
'%admin_email%'
])
->setPublic(true);
// 2. 设置参数
$container->setParameter('admin_email', 'admin@example.com');
// 3. 设置标签
$container->register('app.event_listener', EventListener::class)
->addTag('kernel.event_listener', ['event' => 'kernel.response']);
return $container;
}
}
高级特性
1 自动装配 (Autowiring)
// config/services.yaml
services:
_defaults:
autowire: true # 自动注入
autoconfigure: true # 自动配置
public: false # 默认私有
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests}'
// 控制器中使用
class ProductController extends AbstractController
{
private $productService;
private $entityManager;
// Symfony 会自动注入这些依赖
public function __construct(
ProductService $productService,
EntityManagerInterface $entityManager
) {
$this->productService = $productService;
$this->entityManager = $entityManager;
}
}
2 服务标签 (Service Tags)
// 自定义标签
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
class CustomCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$taggedServices = $container->findTaggedServiceIds('app.processor');
foreach ($taggedServices as $id => $tags) {
// 处理标签服务
$definition = $container->getDefinition($id);
$definition->addMethodCall('setLogger', [
new Reference('logger')
]);
}
}
}
// 服务定义添加标签
services:
App\Service\PdfProcessor:
tags:
- { name: 'app.processor', priority: 10, format: 'pdf' }
3 服务装饰器 (Service Decoration)
// 装饰原有服务
services:
App\Service\OriginalMailer:
class: App\Service\MailerService
App\Decorator\LoggingMailer:
decorates: App\Service\OriginalMailer
decoration_inner_name: 'app.original_mailer'
arguments:
- '@App\Decorator\LoggingMailer.inner'
# 或者使用接口装饰
App\Decorator\CachingMailer:
decorates: App\Service\MailerService
decoration_on_invalid: exception
arguments:
- '@.inner'
4 容器编译优化
// 自定义编译器
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class PerformanceCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
// 1. 优化自动加载
foreach ($container->getDefinitions() as $id => $definition) {
if ($definition->isPublic()) {
$definition->setPublic(false);
$container->setAlias($id, $definition->getClass());
}
}
// 2. 预编译表达式
$container->getParameterBag()->resolve();
// 3. 优化服务延迟加载
foreach ($container->getDefinitions() as $definition) {
$definition->setPublic(false);
if (!$definition->isLazy()) {
$definition->setLazy(true);
}
}
}
}
实际应用示例
1 复杂依赖注入
// services.yaml
services:
App\Service\OrderService:
arguments:
$connection: '@database_connection'
$eventDispatcher: '@event_dispatcher'
$logger: '@monolog.logger.order'
calls:
- ['setCache', ['@cache.app']]
tags:
- { name: 'monolog.logger', channel: 'order' }
// 注入配置参数
parameters:
orders.payment.timeout: 3600
orders.shipping.methods: ['standard', 'express', 'next_day']
services:
App\Service\PaymentService:
arguments:
$config:
timeout: '%orders.payment.timeout%'
methods: '%orders.shipping.methods%'
2 动态服务创建
// 工厂模式
class ServiceFactory
{
public static function create(string $type): ServiceInterface
{
switch ($type) {
case 'email':
return new EmailService();
case 'sms':
return new SmsService();
default:
throw new \InvalidArgumentException();
}
}
}
// services.yaml
services:
App\Service\NotificationService:
factory: ['App\Factory\ServiceFactory', 'create']
arguments:
- '%notification_type%'
性能优化技巧
// 1. 参数注入优化
services:
_defaults:
bind:
string $projectDir: '%kernel.project_dir%'
// 2. 服务懒加载
services:
App\Service\ExpensiveService:
lazy: true # 惰性加载直到使用时才实例化
// 3. 共享服务 vs 非共享服务
services:
App\Service\SharedService:
shared: true # 单例模式(默认)
App\Service\NonSharedService:
shared: false # 每次获取新实例
// 4. 常量注入
services:
App\Service\EnvAwareService:
arguments:
$env: !php/const App\Kernel::ENVIRONMENT
$debug: '%kernel.debug%'
容器调试命令
# 显示所有服务 php bin/console debug:container # 显示特定服务详情 php bin/console debug:container App\Service\MailService # 显示服务参数 php bin/console debug:container --parameters # 显示服务标签 php bin/console debug:container --tags # 显示自动装配服务 php bin/console debug:autowiring
最佳实践建议
// 1. 优先使用构造器注入
class UserService {
public function __construct(
private UserRepository $repository,
private LoggerInterface $logger
) {}
}
// 2. 避免循环依赖
// 坏示例
class A { public function __construct(B $b) {} }
class B { public function __construct(A $a) {} } // 循环依赖!
// 好 - 使用事件或服务定位器
class A {
public function __construct(EventDispatcherInterface $dispatcher) {}
}
// 3. 使用依赖注入而不是服务定位器
// 避免这样做
class BadClass {
public function doSomething() {
$container = $this->getContainer();
$service = $container->get('app.service');
}
}
// 应该这样做
class GoodClass {
public function __construct(
private MyService $service
) {}
}
Symfony 的 DI 容器提供了强大而灵活的服务管理机制,正确使用可以显著提升代码的可维护性和可测试性。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播