背景
最近在看项目中前辈的代码,发现使用队列发送消息的时候,从一开始整合发送消息需要数据的时候,就一直携带者实例化好的sendMessage类,项目中又将推送资料和推送会议分成了两个队列,所以在好些个方法中都有这个sendMessage对象;而且sendMessage实例化时,又依赖其他的类; 所以这个就让我想起来了laravel的核心 Provider
了解laravel的工作原理
所以laravel服务容器就像一个高度自动化的工厂,你需要的东西,定制好模型,使用特定接口来制造就可以了;而且它可以在实例化的时候解决你需要的一些依赖的类的问题;
原发送消息执行流程
- 实际发送逻辑汇总
SendMessage.php
class SendMessage{
protected $mailService; // 发送邮件的服务
public function __construct(SendMailService $mailService)
{
$this->mailService = $mailService;
}
public function send(array $data, $sender = null, $receiver = null, $module = null, $from = null, $push_url = null, $is_type = false)
{
}
}
- 队列执行,发送功能
class RecommendJob implements ShouldQueue
{
private $sendMessage;
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct($sendMessage, $recommend, $message, $channel, $from= null)
{
//
$this->sendMessage = $sendMessage;
}
public function handle()
{
$this->sendMessage->send($data,$sender,$receiver)
}
}
这里你可以看出,队列在执行发送消息时,是从上一级直接获取的sendMessage实例,也就是说在放入消息进队列的执行了实例化,并携带该对象层层传递,且哪里有消息需要放入队列,哪里就要实例化一次sendMessage;当然这里实例化并不是使用new 的形式来操作的,是使用依赖注入的方式,这也是一种好的方法,
现发送消息执行流程
-
实际发送逻辑汇总
这个我就不用调整了 -
队列执行,发送功能
class SendEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $user;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($recommend, $message, $channel, $from= null)
{
//
$this->user = $message;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//调用发送消息
app('sendMessage')->send($data, $this->user ,$receiver);
}
}
这样在消息入队列的时候,就只需要传递需要的信息,而且在调用队列的时候也不用提前实例。
主要是当项目执行的时候,会在index.php加载app.php,在这里面检索laravel应用程序的实例。(laravel本身采取的第一个动作就是创建一个应用程序/服务容器)
所以你需要写一个服务提供者,将事物绑定到服务容器上,然后app才能直接实例;
服务提供器是所有laravel应用程序的引导中心。引导可以理解为注册,比如注册服务容器绑定、时间监听器、中间件甚至路由等。所以自我新增的服务容器除了要绑定事物外,还要注册,就是放在config/app.php配置文件中去;这时第一步:所有的服务提供者的register方法会被调用,然后等到所有的均注册后,boot方法会被调用;这样就将自己创建的服务容器者放在了laravel中的IOC容器中去了,这样项目执行时,就可以使用app来直接使用新建的服务容器
新增一个服务提供者
php artisan make:provider EmailServiceProvide
class EmailServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->registerEmailService();
}
protected function registerEmailService(){
$this->app->bind('sendMessage',function () {//单例模式,直接使用singleton方法绑定关系
return new SendMessage(new MailService());
});
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}
其实这里bind方法的第一个参数,你可以当作是个key,第二个方法中返回的就是类;这样当调用类的时候,就直接使用app(key)可以了,简单易懂
在此需要说明的有:
1.在new SendMessage时,假如这里不仅支持邮件发送,还有短信发送,只需要直接调整为:
$this->app->bind(‘sendMessage’,function () {//单例模式,直接使用singleton方法绑定关系
return new SendMessage(new MailService(), new SmsService());
});
2.服务提供者是支持单例模式的,所以想调整为单例时,只需要直接将bind调整为singleton方式即可,
写在最后
这只是我个人的浅浅的了解,越学习越感觉无知