AOP

    AOP 的概念通过搜索引擎一定是看烦了,而且看了也没什么大卵用,不贴近实际。

    我先举个 AOP 实际应用的简单例子,比如在写一个方法的时候,可能要针对某个方法写前置和后置操作,传统写法如下:

    运行结果:

    1. Parent->test()

    这种写法你需要事先定义好前置和后置方法,如果需要前后置的方法一多,写起来会非常繁琐。

    AOP 可以很好地解决这个问题,不仅可以在编写上不用事先定义这么多方法,还非常有助于解耦。

    普通的类,你要切入的类。

    切入点 Pointcut

    普通类中的方法,你要切入的方法。

    通知 Advice

    在连接点触发的通知,比如在前置操作触发,通知里写前置的具体实现。

    IMI 支持的通知点有:

    前置操作

    后置操作

    环绕操作。先触发环绕操作,在前置操作前和后置操作后,都可以做一些事情。甚至可以完全不让原方法运行,在环绕中实现该方法功能。

    在原方法返回后触发,可以修改返回值

    在抛出异常后触发,允许设置allowdeny,设置允许和拒绝捕获的异常类

    运行效果:

    1. after Imi\Redis\CoroutineRedisPool::getResource(): 0/1
    2. after Imi\Redis\CoroutineRedisPool::release(): 1/1

    类名、方法名和命名空间没有要求,只要beanScan里能扫描到即可。

    类注释中必须写@Aspect表名是一个切面类

    方法中写表示指定切入点,支持通配符

    @After代表在该方法调用后触发

    配置注入

    实现代码

    对类没有任何要求,方法只需要参数对即可。

    配置

    1. <?php
    2. return [
    3. // 类名
    4. \Test\Test::class => [
    5. // 固定写法methods
    6. 'methods' => [
    7. 'test' => [
    8. // 指定切入点
    9. 'pointCut' => [
    10. 'allow' => [
    11. "Imi\*Pool*::getResource",
    12. "Imi\*Pool*::release",
    13. ]
    14. ],
    15. 'after' => [
    16. ]
    17. ]
    18. ],
    19. ];

    如下代码例子,定义一个类,使用@Inject注解来注释属性,在通过实例化时,会自动给被注释的属性赋值相应的实例对象。

    1. namespace Test;
    2. class TestClass
    3. {
    4. /**
    5. * 某Model对象
    6. * @Inject("XXX\Model\User")
    7. */
    8. protected $model;
    9. public function test()
    10. {
    11. var_dump($model->toArray());
    12. }
    13. }