首页 > 其他分享 >laravel 中实现注解注入

laravel 中实现注解注入

时间:2024-10-16 14:37:03浏览次数:1  
标签:laravel App app reflectionProperty 注解 injection php Injection 注入

laravel 中实现注解注入

创建注解类

<?php

declare(strict_types=1);

namespace App\Support\Attributes;

#[\Attribute(\Attribute::TARGET_PROPERTY)]
readonly class Injection
{
    public function __construct(
        public ?string $propertyType = null,
        public array $parameters = []
    ) {}
}

引导解析注解

<?php

declare(strict_types=1);

namespace App\Providers;

use App\Support\Attributes\Injection;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void {}

    public function boot(): void
    {
        $this->injection();
    }

    private function injection(): void
    {
        $this->app->resolving(static function (mixed $object, Application $app): void {
            if (! \is_object($object)) {
                return;
            }

            $class = str($object::class);
            if (
                ! $class->is(config('services.injection.only'))
                || $class->is(config('services.injection.except'))
            ) {
                return;
            }

            $reflectionObject = new \ReflectionObject($object);

            foreach ($reflectionObject->getProperties() as $reflectionProperty) {
                if (! $reflectionProperty->isDefault() || $reflectionProperty->isStatic()) {
                    continue;
                }

                $attributes = $reflectionProperty->getAttributes(Injection::class);
                if ($attributes === []) {
                    continue;
                }

                /** @var Injection $injection */
                $injection = $attributes[0]->newInstance();

                $propertyType = value(static function () use ($injection, $reflectionProperty, $reflectionObject): string {
                    if ($injection->propertyType) {
                        return $injection->propertyType;
                    }

                    $reflectionPropertyType = $reflectionProperty->getType();
                    if ($reflectionPropertyType instanceof \ReflectionNamedType && ! $reflectionPropertyType->isBuiltin()) {
                        return $reflectionPropertyType->getName();
                    }

                    throw new \LogicException(\sprintf(
                        'Attribute [%s] of %s miss a argument, or %s must be a non-built-in named type.',
                        Injection::class,
                        $property = "property [{$reflectionObject->getName()}::\${$reflectionProperty->getName()}]",
                        $property,
                    ));
                });

                $reflectionProperty->isPublic() or $reflectionProperty->setAccessible(true);
                $reflectionProperty->setValue($object, $app->make($propertyType, $injection->parameters));
            }
        });
    }
}

配置解析范围(可选)

config/services.php

<?php

return [
    // ...

    'injection' => [
        'only' => [
            'App\*',
        ],
        'except' => [
            'App\Support\Macros\*',
        ],
    ],
];

使用

示例

<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Support\Attributes\Injection;
use App\Support\HmacSigner;
use Illuminate\Config\Repository;

class TestCommand extends \Illuminate\Console\Command
{
    protected $signature = 'test';

    #[Injection('path.storage')]
    private string $storagePath;

    #[Injection(parameters: ['secret' => 'secret...'])]
    private HmacSigner $hmacSigner;

    #[Injection(Repository::class)]
    private Repository $repositoryOfInjectionPropertyType;

    #[Injection('config')]
    private Repository $repositoryOfInjectionInstanceKey;

    #[Injection]
    private Repository $repositoryOfReflectionPropertyType;

    public function handle(): void
    {
        dump(
            $this->storagePath,
            $this->hmacSigner,
            $this->repositoryOfInjectionPropertyType->get('services.injection'),
            $this->repositoryOfInjectionInstanceKey->get('services.injection.only'),
            $this->repositoryOfReflectionPropertyType->get('services.injection.except'),
        );
    }
}

输出

╰─ ./artisan test                                                                                ─╯
"/Users/yaozm/Documents/wwwroot/laravel-skeleton/storage" // app/Console/Commands/TestCommand.php:32
App\Support\HmacSigner {#2045
  -secret: "secret..."
  -algo: "sha256"
} // app/Console/Commands/TestCommand.php:32
array:2 [
  "only" => array:1 [
    0 => "App\*"
  ]
  "except" => array:1 [
    0 => "App\Support\Macros\*"
  ]
] // app/Console/Commands/TestCommand.php:32
array:1 [
  0 => "App\*"
] // app/Console/Commands/TestCommand.php:32
array:1 [
  0 => "App\Support\Macros\*"
] // app/Console/Commands/TestCommand.php:32

与依赖注入比较

功能 注解注入 依赖注入
标量类型 已支持 未支持
传参 已支持 未支持

相关连接

原文连接

标签:laravel,App,app,reflectionProperty,注解,injection,php,Injection,注入
From: https://www.cnblogs.com/guanguans/p/18469880

相关文章

  • laravel11: 开启optimize和不开启optimize的区别有多大?
    一,测试环境:PHP8.3.9LaravelFramework11.15.0接口没访问数据,只是从redis取数据测试前已开启opcache+jit二,未开启optimize时访问10次测试前先执行4个clear,避免有之前做的cacheroot@lhdpc:/data/api#phpartisanroute:clearINFORoutecacheclearedsuccessfull......
  • spring上 -基于注解配置bean,动态代理,AOP笔记
     用的是jdk8,spring框架里jar包的下载可以自己搜到注解用到的jar包。  60,注解配置Bean快速入门 基本介绍 代码结构: UserDao.javapackagecom.hspedu.spring.component;importorg.springframework.stereotype.Repository;/**使用@Repository标识该......
  • sql手工注入获取库、表名(union联合注入)(个人学习笔记)
    1,发现存在sql漏洞的网站当我们发现一个网站存在sql注入的漏洞时,可以使用sql手工注入来获取信息,如下列的网站sql注入的原理是前端给后端发送指令的时候由于设计者未考虑安全,导致用户可以加上自己的指令进去,从而让服务器完成一些列危险的操作2,确定列表数名首先,我们要先知道......
  • Python入门-面相对象——class(类)、封装、继承、多态、类型注解
    面向对象面向对象就是设计一个类,基于类创建对象,并使用创建出来的类完成具体的工作面向对象的三大特性:封装、继承、多态面向对象基本概述:属性:名词,用来描述事物的外在特征的,例如:姓名,性别,年龄,身高,体重...行为:动词,表示事物能够做什么,例如:......
  • ABP VNext 系列:框架启动流程以及依赖注入原理和源码分析
    简单介绍ABPVNextGithub地址:https://github.com/abpframework/abp官网文档地址:https://abp.io/docs/latest官网:https://abp.io/ABPVNext框架是一个基于ASP.NETCore的完整基础架构,也就是我们现在称的ABP框架,它遵循软件开发最佳实践和最新技术来创建现代Web应用程......
  • EF Core 中避免 SQL 注入的三种写法
    SQL注入攻击可能会对我们的应用程序产生严重影响,导致敏感数据泄露、未经授权的访问和应用程序受损。EFCore提供了三种内置机制来防止SQL注入攻击。1、利用LINQ查询语法和参数化查询,这是比较推荐的做法。awaitusingvarcontext=newPostgresContext();varauthor=......
  • [Spring] 深入理解: Spring @Value 解析、注入时机及原理
    内容摘要:@Value的使用及它是什么时候解析的并且解析后是如何注入值的?1@Value的使用简述@Value注解可用来将外部的值动态注入到Bean中,在@Value注解中,可以使${}与#{},它们的区别如下:(1)@Value("${}"):可以获取对应属性文件中定义的属性值。(2)@Value("#{}"):表示Sp......
  • Spring注解之 @Autowired @Qualifier
    在Spring框架中,@Autowired和@Qualifier是两个常用注解,用于依赖注入(DependencyInjection)时选择和管理Spring容器中的Bean。1.@Autowired@Autowired注解用于自动注入依赖项。Spring容器会自动将符合类型的Bean注入到带有@Autowired注解的字段、构造器或方法......
  • Java中注解的学习
    元注解目录元注解什么是元注解5种元注解@Retention@Documented@Target@Inherited@Repeatable什么是元注解元注解是用于定义注解的注解(或者说元注解是一种基本注解,它能够应用到其它的注解上面);元注解也是一张标签,但是它是一张特殊的标签,它的作用和目的就是给其他普通的标签进行......
  • SQL注入基础速通
    <aside>......