欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長(zhǎng)資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          解析ThinkPHP5如何引入Go AOP和PHP AOP編程

          項(xiàng)目背景

          目前開(kāi)發(fā)的WEB軟件里有這一個(gè)功能,PHP訪問(wèn)API操作數(shù)據(jù)倉(cāng)庫(kù),剛開(kāi)始數(shù)據(jù)倉(cāng)庫(kù)小,沒(méi)發(fā)現(xiàn)問(wèn)題,隨著數(shù)據(jù)越來(lái)越多,調(diào)用API時(shí)常超時(shí)(60s)。于是決定采用異步請(qǐng)求,改為60s能返回?cái)?shù)據(jù)則返回,不能則返回一個(gè)異步ID,然后輪詢是否完成統(tǒng)計(jì)任務(wù)。由于項(xiàng)目緊,人手不足,必須以最小的代價(jià)解決當(dāng)前問(wèn)題。

          方案選擇

          1. 重新分析需求,并改進(jìn)代碼
          2. 采用AOP方式改動(dòng)程序

          從新做需求分析,以及詳細(xì)設(shè)計(jì),并改動(dòng)代碼,需要產(chǎn)品,架構(gòu),前端,后端的支持。會(huì)驚動(dòng)的人過(guò)多,在資源緊張的情況下是不推薦的。
          采用AOP方式,不改動(dòng)原有代碼邏輯,只需要后端就能完成大部分任務(wù)了。后端用AOP切入請(qǐng)求API的方法,通過(guò)監(jiān)聽(tīng)API返回的結(jié)果來(lái)控制是否讓其繼續(xù)運(yùn)行原有的邏輯(API在60s返回了數(shù)據(jù)),或者是進(jìn)入離線任務(wù)功能(API報(bào)告統(tǒng)計(jì)任務(wù)不能在60s內(nèi)完成)。

          之前用過(guò)AOP-PHP拓展,上手很簡(jiǎn)單,不過(guò)后來(lái)在某一個(gè)大項(xiàng)目中引入該拓展后,直接爆了out of memory,然后就研究其源碼發(fā)現(xiàn),它改變了語(yǔ)法樹(shù),并Hook了每個(gè)被調(diào)用的方法,也就是每個(gè)方法被調(diào)用是都會(huì)去詢問(wèn)AOP-PHP,這個(gè)方法有沒(méi)有切面方法。所以效率損失是比較大的。而且這個(gè)項(xiàng)目距離現(xiàn)在已經(jīng)有8年沒(méi)更新了。所以不推薦該解決方案。

          實(shí)際環(huán)境

          Debian,php-fpm-7.0,ThinkPHP-5.10。

          引入AOP

          作為一門zui好的語(yǔ)言,PHP是不自帶AOP的。那就得安裝AOP-PHP拓展,當(dāng)我打開(kāi)pecl要下載時(shí),傻眼了,全是bate版,沒(méi)有顯示說(shuō)明支持php7。但我還是抱著僥幸心理,找到了git,發(fā)現(xiàn)4-5年沒(méi)更新了,要不要等一波更新,哦,作者在issue里說(shuō)了有時(shí)間就開(kāi)始兼容php7。
          好吧,狠話不多說(shuō),下一個(gè)方案:Go!AOP.看了下git,作者是個(gè)穿白體恤,喜歡山峰的大帥哥,基本每個(gè)issue都會(huì)很熱心回復(fù)。

          composer require goaop/framework

          ThinkPHP5 對(duì)composer兼容挺不錯(cuò)的哦,(到后面,我真想揍ThinkPHP5作者)這就裝好了,怎么用啊,git上的提示了簡(jiǎn)單用法。我也就照著寫了個(gè)去切入controller。

          <?PHP namespace apptestscontroller;  use thinkController;  class Test1 extends Controller {     public function test1()     {         echo $this->aspectAction();     }          public function aspectAction()     {         return 'hello';     } }

          定義aspect

          <?PHP namespace apptestsaspect;  use GoAopAspect; use GoAopInterceptFieldAccess; use GoAopInterceptMethodInvocation; use GoLangAnnotationAfter; use GoLangAnnotationBefore; use GoLangAnnotationAround; use GoLangAnnotationPointcut;  use apptestscontrollerTest1;  class MonitorAspect implements Aspect {      /**      * Method that will be called before real method      *      * @param MethodInvocation $invocation Invocation      * @Before("execution(public|protected apptestscontrollerTest1->aspectAction(*))")      */     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";     } }

          啟用aspect

          <?PHP // file: ./application/tests/service/ApplicationAspectKernel.php  namespace apptestsservice;  use GoCoreAspectKernel; use GoCoreAspectContainer;  use apptestsaspectMonitorAspect;  /**  * Application Aspect Kernel  *  * Class ApplicationAspectKernel  * @package apptestsservice  */ class ApplicationAspectKernel extends AspectKernel {      /**      * Configure an AspectContainer with advisors, aspects and pointcuts      *      * @param AspectContainer $container      *      * @return void      */     protected function configureAop(AspectContainer $container)     {         $container->registerAspect(new MonitorAspect());     } }

          go-aop 核心服務(wù)配置

          <?PHP // file: ./application/tests/behavior/Bootstrap.php namespace apptestsbehavior;  use thinkException; use ComposerAutoloadClassLoader; use GoInstrumentTransformerFilterInjectorTransformer; use GoInstrumentClassLoadingAopComposerLoader; use DoctrineCommonAnnotationsAnnotationRegistry;  use apptestsserviceApplicationAspectKernel; use apptestsThinkPhpLoaderWrapper;  class Bootstrap {     public function moduleInit(&$params)     {         $applicationAspectKernel = ApplicationAspectKernel::getInstance();         $applicationAspectKernel->init([             'debug' =>  true,             'appDir'    =>  __DIR__ . './../../../',                 'cacheDir'  =>  __DIR__ . './../../../runtime/aop_cache',                 'includePaths'  =>  [                     __DIR__ . './../../tests/controller',                     __DIR__ . './../../../thinkphp/library/think/model'                 ],                 'excludePaths'  =>  [                     __DIR__ . './../../aspect',                 ]             ]);         return $params;     } }

          配置模塊init鉤子,讓其啟動(dòng) go-aop

          <?PHP // file: ./application/tests/tags.php // 由于是thinkphp5.10 沒(méi)有容器,所有需要在module下的tags.php文件里配置調(diào)用他  return [     // 應(yīng)用初始化     'app_init'     => [],     // 應(yīng)用開(kāi)始     'app_begin'    => [],     // 模塊初始化     'module_init'  => [         'app\tests\behavior\Bootstrap'     ],     // 操作開(kāi)始執(zhí)行     'action_begin' => [],     // 視圖內(nèi)容過(guò)濾     'view_filter'  => [],     // 日志寫入     'log_write'    => [],     // 應(yīng)用結(jié)束     'app_end'      => [], ];

          兼容測(cè)試

          好了,訪問(wèn) http://127.0.0.1/tests/test1/… 顯示:

          hello

          這不是預(yù)期的效果,在aspect定義了,訪問(wèn)該方法前,會(huì)輸出方法的

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)