Interface injection

In an actual business scenario, many situations require interface-oriented programming, and the object actually implemented by the interface needs to be injected according to the interface class name. Interface-oriented programming can be very convenient to decouple the service, as an example of sending a text message as follows.

2.0.3 Start support

Annotation injection

 use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Bean\Annotation\Mapping\Inject;
use Swoft\Bean\Annotation\Mapping\Primary;
use Swoft\Bean\BeanFactory;

interface SmsInterface
{
    public function send(string $content): bool;
}

/**
 * Class AliyunSms
 *
 * @since 2.0
 *
 * @Bean()
 * @Primary()
 */
class AliyunSms implements SmsInterface
{
    /**
     * @param string $content
     *
     * @return bool
     */
    public function send(string $content): bool
    {
        return true;
    }
}

/**
 * Class QcloudSms
 *
 * @since 2.0
 *
 * @Bean()
 */
class QcloudSms implements SmsInterface
{
    /**
     * @param string $content
     *
     * @return bool
     */
    public function send(string $content): bool
    {
        return true;
    }
}

/**
 * Class Sms
 *
 * @since 2.0
 *
 * @Bean()
 */
class Sms implements SmsInterface
{
    /**
     * @Inject()
     *
     * @var SmsInterface
     */
    private $smsInterface;

    /**
     * @param string $content
     *
     * @return bool
     */
    public function send(string $content): bool
    {
        return $this->smsInterface->send($content);
    }
}

/* @var SmsInterface $sms*/
$sms = BeanFactory::getBean(Sms::class);

// Send Aliyun sms
$sms->send('sms content'); 

The current example is to send Alibaba Cloud SMS. If the business changes, you need to use Gcloud to send SMS. Just remove the AliyunSms @Primary() annotation and add this annotation to the Qcloud class to completely decouple the business code. modify.

@Inject() injection bean name is empty, it will give priority to inject @Primary() annotation instance of an object mark, if not empty, such as @Inject(QcloudSms::class) will be injected into the specified instance of an object.

@Primary

If an interface has multiple implementations, this tag is the object used when the interface is injected. Only one of the multiple implementation classes of the same interface can have this annotation tag.

Configuration injection

The bean configuration (app\bean.php) also supports interface injection. For example, the Sms sending SMS messages is modified without annotation. The other changes are as follows:

 /**
 * Class Sms
 *
 * @since 2.0
 */
class Sms implements SmsInterface
{
    /**
     * @var SmsInterface
     */
    private $smsInterface;

    /**
     * @param string $content
     *
     * @return bool
     */
    public function send(string $content): bool
    {
        return $this->smsInterface->send($content);
    }
} 

The bean in the app\bean.php file

 [
   Sms::class => [
        'smsInterface' => bean(SmsInterface::class)
   ]
] 

The code is saved unchanged, and its implementation is the same as the annotation method.

 /* @var SmsInterface $sms*/
$sms = BeanFactory::getBean(Sms::class);

// Send Aliyun sms
$sms->send('sms content'); 
/docs/2.x/en/bean/interface.html
progress-bar