Trong các framework có Dependency Injection / IoC như Laravel hay Spring Framework, hai khái niệm Service Container và Service Provider thường đi cùng nhau nhưng vai trò hoàn toàn khác. Nhiều người mới học thường nhầm chúng là một.
Mình giải thích theo đúng bản chất để bạn dễ hình dung khi đọc code framework.
Service Container là nơi lưu trữ và tạo ra các object của ứng dụng.
Nó giống như một "nhà máy tạo object" + "kho chứa object".
Khi ứng dụng cần một class, container sẽ:
Ví dụ trong Laravel:
$service = app()->make(OrderService::class);
hoặc
$service = $container->resolve(OrderService::class);
Quá trình xảy ra:
Controller ↓ Service Container ↓ OrderService ↓ Database / Logger / Mailer
Container sẽ:
new OrderService(new PaymentService(), new Logger())
tự động.
class Container {
protected $bindings = [];
public function bind($name, $class) {
$this->bindings[$name] = $class;
} public function resolve($name) {
$class = $this->bindings[$name];
return new $class();
}
}
Service Provider là nơi đăng ký các service vào Service Container.
Nó giống như file cấu hình cho container.
Ví dụ:
class OrderServiceProvider {
public function register($container) {
$container->bind(OrderService::class, function () {
return new OrderService(new PaymentService());
});
}}
Khi application start:
App Boot ↓ Load Service Providers ↓ Register Services vào Container ↓ Application chạy
Trong Laravel có file:
app/Providers/AppServiceProvider.php
public function register()
{
$this->app->bind(
PaymentInterface::class,
StripePayment::class
);
}
Ở đây:
$this->app = Service Container
Service Provider chỉ đăng ký.
Khi code gọi:
app(PaymentInterface::class);
container sẽ trả:
StripePayment instance
| Thành phần | Vai trò |
|---|---|
| Service Container | nơi tạo và quản lý object |
| Service Provider | nơi đăng ký object vào container |
Hiểu đơn giản:
Service Provider = nơi cấu hình Service Container = nơi chạy thực tế
hoặc
Service Provider -> đăng ký service Service Container -> tạo service
Toàn bộ flow:
Application start
↓
Load Service Providers
↓
Register services vào Container
↓
Application cần object
↓
Container resolve object
↓
Dependency Injection
Giả sử hệ thống thanh toán.
Service:
PaymentInterface StripePayment PaypalPayment
Service Provider:
$this->app->bind(PaymentInterface::class, StripePayment::class);
Controller:
class OrderController { public function __construct(PaymentInterface $payment) {
$this->payment = $payment;
}}
Container sẽ tự làm:
new OrderController(
new StripePayment()
)
Service Container = Object Factory Service Provider = Service Registration
hoặc
Provider = khai báo Container = thực thi