YII2集成GOAOP,实现面向方面编程!

引言:
  软件开发的对象是要是针对性世界的部分因素或信息流建立模型,实现软件系统的工程需要拿系统分解成可以创造及治本的模块。于是应运而生了为网模块化特性的面向对象程序设计技术。模块化的面向对象编程极度地加强了软件系统的可读性、复用性和可扩展性。向目标方法的症结在于选择对象作为模块的显要单元,并以目标和网的所有行止联系起来。对象变成问题领域与测算过程的机要因素。但面向对象技术并从未于精神上化解软件系统的但是复用性。创建软件系统时常,现实问题受到是在重重横切关注点,比如安全性检查、日志记录、性能监控,异常处理等,它们的兑现代码和任何作业逻辑代码混杂在同,并分散于软件不同地方(直接把拍卖这些操作的代码加入到每个模块中),这无疑破坏了OOP的”单一任务”原则,模块的可重用性会大大降低,这令软件系统的可维护性和复用性受到大限制。这时候传统的OOP设计反复利用的方针是进入相应的代办(Proxy)层来成功系统的功用要求,但这么的拍卖肯定要系统总体增加了一个层次之撤并,复杂性也随着增加,从而被丁过于沉重的感觉到。由此发出了面向方面编程(AOP)技术。这种编程模式抽取出散落于软件系统所在的横切关注点代码,并模块化,归整到同,这样进一步提高软件的可维护性、复用性和可扩展性。

AOP简介:
AOP: Aspect Oriented Programming 面向切面编程。
  面向切面编程(也为面向方面):Aspect Oriented
Programming(AOP),是目前软件开发中之一个吃香。利用AOP可以针对业务逻辑的相继组成部分开展隔离,从而使得业务逻辑各部分中的耦合度降低,提高程序的但重用性,同时加强了出之效率。
  AOP是OOP的继续,是(Aspect Oriented
Programming)的缩写,意思是面向切面(方面)编程。
  主要的成效是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
  主要的打算是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从事情逻辑代码中分出,通过对这些作为之分别,我们要可以拿其独立及无指导业务逻辑的方法吃,进而改变这些作为的时不影响工作逻辑的代码。
  可以经过预编译方式跟运行期动态代理实现在匪修改源代码的动静下深受程序动态统一上加效果的同样种植技术。AOP实际是GoF设计模式的持续,设计模式孜孜不倦追求的凡调用者和为调用者之间的解耦,AOP可以说也是这种对象的等同栽实现。
比方把应用程序想成为一个立体结构吧,OOP的利刃是不怕为切入系统,把系统划分也多单模块(如:用户模块,文章模块等等),而AOP的利刃是横向切入系统,提取各个模块可能都使重新操作的一对(如:权限检查,日志记录等等)。由此可见,AOP是OOP的一个行之有效填补。
在意:AOP不是平种植技术,实际上是编程思想。凡是符合AOP思想之技巧,都可看做是AOP的实现。

AOP 的基本概念:
在面向对象编程中,类,对象,封装,继承,多态等概念是描述面向对象思想要术语。与之类似,在面向方面编程中,同样存在着有些基本概念:
       联结点(JointPoint)
:一个联程序执行过程遭到之一个一定点。典型的联结点有:调用一个法;方法执行这个过程自己;类初始化;对象初始化等。联结点是
AOP 的为主概念有,它因此来定义在先后的乌通过 AOP 加入新的逻辑。
        切入点(Pointcut)
:一个切入点是故来定义有一个通告该何时实施的相同组联结点。通过定义切入点,我们可规范地操纵程序中什么组件接到什么通知。上面我们干,一个超人的联结点是法调用,而一个独立的切入点就是对有一个看似的各地方法调用的会师。通常我们见面透过组建复杂的切入点来控制通知什么时吃执行。
        通知(Advice)
:在某一个特定的联结点处运行的代码称为“通知”。通知发出众多种,比如
每当联结点之前实施的置通知(before
advice)和于联结点之后执行之后置通知(after advice) 。
       方面(Aspect)
:通知以及切入点的整合叫做方面,所以,方面定义了千篇一律段落先后中应有包括的逻辑,以及何时应该实行该逻辑。
       织入(Weaving) :织入是以方面的确加入程序代码的经过。对于静态
AOP
方案而言,织入是当编译时成功的,通常是以编译过程中长一个步骤。类似的,动态
AOP 方案则是于程序运行是动态织入的。
       目标(Target) :如果一个目标的推行进程中某一个 AOP
的改,那么其便深受一个对象靶。目标靶一般为号称被通知对象。
       引入(Introduction) :  
通过引入,可以在一个靶中投入新的道或者性能,以转其的组织,这样就是该目标的好像没有实现有一个接口,也可以改其,使之变成该接口的一个贯彻。 
 

       静态和动态:静态 AOP 和动态 AOP
两者之间的分别主要在于什么时间织入,以及哪些织入。最早的 AOP
实现多还是静态的。在静态 AOP 中,织入是编译过程的一个步骤。用Java
的术语说,静态 AOP
通过一直指向许节码进行操作,包括修改代码和扩展类,来形成织入过程。显然,这种方式生成的次序性能大好,因为最后的结果就是是一般的
Java
字节码,在运行时不再用专门的技艺来确定什么时应该实施通知。这种方法的败笔是,如果想对地方举行什么修改,即使只有是加入一个初的联结点,都要还编译整个程序。AspectJ
是静态 AOP 的一个名列前茅事例。与静态 AOP 不同,动态 AOP
中织入是以运作时动态完成的。织入具体是怎样完成的,各个实现有所不同。Spring
AOP 采取的法门是树立代办,然后代理于适宜的时节实施通知。动态 AOP
的一个毛病就是在,其性一般不使静态 AOP。而动态AOP
的严重性优点在于可天天修改程序的保有地方,而未待另行编译目标。

AOP实践:
YII2框架本身有所一个力量,叫做行为.它好动态的吧目前底切近附加额外的功效,但这种力量于代码层级结构是静态的,有侵入性的。

下面为YII2框架集成go!aop库为例,介绍于YII2中什么促成AOP编程.(go!aop简介,可以参照go!aop的官网.)

出于YII框架拥有和谐之近乎加载器,所在集成go!aop的时刻,不可知健康的工作,所以如果以那受用少,使用composer提供的类似加载器。
一般来说代码所示(这里运用YII2高档应用模板):

1、找到  spl_autoload_register([‘Yii’, ‘autoload’], true, true); 
(PROJECT_PATH/vendor/yiisoft/yii2/Yii.php) 将那个受用掉.

2、执行  composer require goaop/framework

3、修改composer.json文件,加入如下代码段:

 "autoload": {
        "psr-4": {
          "backend\\": "backend//",
          "frontend\\": "frontend//",
          "common\\": "common//"
        }
  }

4、 在frontend
目录下创造一个components是目录,并新建一个类AopAspectKernel,例如:

namespace frontend\components;
use frontend\aspects\MonitorAspect;
use Go\Core\AspectContainer;
use Go\Core\AspectKernel;
class AopAspectKernel extends AspectKernel
{
        protected function configureAop(AspectContainer $container)
        {
            $container->registerAspect(new MonitorAspect());
        }
}

 
5、在forntend目录下于新建一个类InitAopComponent,并要该实现BootstrapInterface,使其好当YII2框架引导时为活动引导

namespace frontend\components;
use yii\base\BootstrapInterface;
class InitAopComponent implements BootstrapInterface
{
        public function bootstrap($app)
        {
            print_r(\Yii::$app->params['aop']);
            $applicationAspectKernel = AopAspectKernel::getInstance();
            $applicationAspectKernel->init(\Yii::$app->params['aop']);
        }
}

 
6、在frontend/config/params.php中新增如下代码:

 'aop' => [
        'debug' => true,
        'appDir' => dirname(__DIR__),
        'cacheDir' => dirname(__DIR__) . '/runtime/aop',
        'includePaths' => [
            dirname(__DIR__)
        ]
    ]

 
7、在frontend下面新建aspects目录,并新建类MonitorAspect,代码如下:

namespace frontend\aspects;

use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Before;
class MonitorAspect implements Aspect
{
        /**
         * Method that will be called before real method
         *
         * @param MethodInvocation $invocation Invocation
         * @Before("execution(public frontend\components\AopTestComponent->*(*))")
         */
        public function beforeMethodExecution(MethodInvocation $invocation)
        {
            $obj = $invocation->getThis();
            echo 'Calling Before Interceptor for method: ',
            is_object($obj) ? get_class($obj) : $obj,
            $invocation->getMethod()->isStatic() ? '::' : '->',
            $invocation->getMethod()->getName(),
            '()',
            ' with arguments: ',
            json_encode($invocation->getArguments()),
            "<br>\n";
        }
}

 
9、修改frontend/config/main.php文件,并于components数组下增产一个key,代码如下:

 'components'=>[
        'aop' => [
            'class' => 'frontend\components\InitAopComponent'
        ]
    ]

 
10、修改frontend/config/main.php文件,并当bootstrap数组下新增aop值,代码如下:

'bootstrap'=>['log','aop']

至此,YII2整合go!aop完成…

 

相关文章