Container cần làm 3 việc chính
Chi tiết hơn
Nói ngắn gọn hơn theo đúng thuật ngữ IoC:
Nhận lớp → phân tích constructor → giải quyết phụ thuộc → tạo đối tượng.
Flow thực tế của Laravel cũng gần như vậy
resolve(Class) ↓ Reflection đọc constructor ↓ resolve các dependency ↓ newInstanceArgs()
class Container
{
public function resolve($class)
{
$reflector = new ReflectionClass($class);
if (!$reflector->isInstantiable()) {
throw new Exception("Class {$class} không thể khởi tạo");
}
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
return new $class;
}
$parameters = $constructor->getParameters();
$dependencies = $this->resolveDependencies($parameters);
return $reflector->newInstanceArgs($dependencies);
}
protected function resolveDependencies($parameters)
{
$dependencies = [];
foreach ($parameters as $parameter) {
$type = $parameter->getType();
if ($type && !$type->isBuiltin()) {
$dependencies[] = $this->resolve($type->getName());
} else {
throw new Exception("Không resolve được dependency");
}
}
return $dependencies;
}
}
Ta tạo 3 class giống hệ thống thật.
class Logger
{
}
class PaymentService
{
public function __construct(Logger $logger)
{
}
}
class OrderService
{
public function __construct(PaymentService $payment)
{
}
}
Dependency graph
OrderService ↓ PaymentService ↓ Logger
$container = new Container(); $orderService = $container->resolve(OrderService::class);
Container sẽ tự tạo toàn bộ dependency.
Thực tế tương đương
new OrderService(
new PaymentService(
new Logger()
)
);
Nhưng ta không cần tự viết tay nữa.
resolve(OrderService)
OrderService::__construct(PaymentService $payment)
resolve(PaymentService)
PaymentService(Logger $logger)
Container tiếp tục
resolve(Logger)
Container tạo luôn
new Logger()
Cuối cùng container gọi
$reflector->newInstanceArgs($dependencies);
Tức là
new OrderService(
new PaymentService(
new Logger()
)
)
Laravel làm y hệt nhưng thêm rất nhiều tính năng
Ví dụ
bind interface
PaymentInterface → StripePayment
singleton
chỉ tạo object 1 lần
instance
đăng ký object sẵn
service provider
đăng ký binding khi boot app
Reflection không tự tiêm dependency
Reflection chỉ làm 2 việc
đọc constructor tạo object
IoC Container mới là thứ
phân tích dependency resolve dependency quản lý lifecycle object