php之aop實踐

來源:互聯網
上載者:User

標籤:

aop簡介

AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程(也叫面向方面),可以通過先行編譯方式和運行期動態代理實現在不修改原始碼的情況下給程式動態統一添加功能的一種技術。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,AOP可以說也是這種目標的一種實現。

 

aop-php簡介

 

AOP-PHP是一個PECL擴充,您可以在PHP中使用面向方面的編程,無需編譯或進行其他任何中間步驟。

AOP擴充的設計是最簡單的方法,你可以認為PHP中的aop實現。

AOP旨在讓橫切關注點的分離(緩衝,日誌,安全,交易,……)

 

網址:http://aop-php.github.io/

 

aop-php安裝安裝

有兩種安裝模式:

第一種方法:

sudo pecl install aop-beta  

第二種方法:

#Clone the repository on your computer    git clone https://github.com/AOP-PHP/AOP    cd AOP    #prepare the package, you will need to have development tools for php    phpize    #compile the package
      ./configure --with-aop --with-php-config=/usr/bin/php-config 
    make    #before the installation, check that it works properly    make test    #install    make install

 

錯誤處理

 

筆者在第二種方法安裝中出現了錯誤(如果沒有錯誤這裡可以飄過):

 

Can‘t locate Autom4te/C4che.pm in @INC (@INC contains: /usr/local/share/autoconf...

 

解決辦法是重新安裝autoconf:

#wget http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz#tar -zxf autoconf-latest.tar.gz#rpm -qf /usr/bin/autoconf #查看autoconf的版本#rpm -e --nodeps autoconf-2.59-12 #卸載原來版本#./configure --prefix=/usr#make && make install

 

編譯安裝成功後,需要在php.ini裡裝載模組,一般在centos裡php的模組裝載在/etc/php.d裡面,建立一個檔案aop.ini ,內容為:

extension=aop.so

 

 安裝成功後查看phpinfo,會看到一下內容:

 

aop-php學前準備

 

專業術語

在實踐之前我們需要先學習哈aop的一些專業術語。

Aspect(切面):橫向切面關係被成組的放進一個類中。Advice(通知):用於調用切面,定義某種情況下做什麼和什麼時間做這件事情。通知又分為:前通知、返回後通知、拋出後通知和周邊通知。Joinpoint(存取點):建立通知的位置。Pointcut(點切割):定義了一種把通知匹配到某些存取點的方式。 具體可以參考這篇部落格:http://www.cnblogs.com/baochuan/archive/2012/08/22/2644529.html 參考文檔 瞭解了這些知識之後我們還需要下載aop-php的說明文檔。官方文檔下載  好了,E文好的可以看官方文檔,直接飄過下面的文字。  準備檔案

在實踐之前我們需要準備四個檔案:測試函數檔案testfunction.php、測試類別檔案testclass.php、測試aop檔案testaop.php和運行檔案test.php。

這樣做可以真實類比我們的項目,大部分的項目都是這樣布局的。

 

aop-php實踐之通知

 

前通知aop_add_before

在代碼中一些特殊點之前使用的通知,正常是調用一個方法或者函數。

我們先測試函數

testfunction.php代碼:

<?phpfunction testFunc1(){    echo ‘aop_add_before <br/>‘;}

testaop.php代碼:

<?php$testpoint1 = function () {echo "這是前切點測試函數:";};aop_add_before(‘testFunc1()‘, $testpoint1);

 

 test.php代碼:

<?phprequire ‘testaop.php‘;require ‘testclass.php‘;require ‘testfunction.php‘;header("Content-Type:text/html;charset=utf-8"); testFunc1();

不出意外,執行test.php我們將會看到:

這是前切點測試函數:aop_add_before 

 

我們再玩哈類

testclass.php代碼:

<?phpclass testClass1{    public function testBeforAdd1()    {        echo get_class($this);    }}

testaop.php代碼:

<?php$testpoint1 = function () {echo "這是前切點測試函數:";};$testpoint2 = function () {echo "這是前切點測試類別方法:";};aop_add_before(‘testFunc1()‘, $testpoint1);aop_add_before(‘testClass1->testBeforAdd1()‘, $testpoint2);

test.php代碼:

<?phprequire ‘testaop.php‘;require ‘testclass.php‘;require ‘testfunction.php‘;header("Content-Type:text/html;charset=utf-8"); testFunc1();$testClass1 = new testClass1();echo $testClass1->testBeforAdd1();

執行test.php

這是前切點測試函數:aop_add_before 這是前切點測試類別方法:testClass1
再測試類別屬性

testclass.php源碼

<?php//測試前通知類class testClass1{    public function testBeforAdd1()    {        echo get_class($this) .‘<br />‘;    }        }//測試前通知類屬性class testClass2{    private $name;    public $publicProperty1 = ‘test‘;    public function __construct ($name)    {        $this->name = $name;    }    public function getName ()    {        return $this->name;    }    public function test ()    {        $this->publicProperty1 = ‘test‘;        return $this->publicProperty1;    }        }

 

testaop.php源碼

<?php$testpoint11 = function  (){    echo "這是前切點測試函數:";};$testpoint12 = function  (){    echo "這是前切點測試類別方法:";};aop_add_before(‘testFunc1()‘, $testpoint11);aop_add_before(‘testClass1->testBeforAdd1()‘, $testpoint12);//------測試類別屬性class changeProperty{    public function shoot ( $who, $what)    {        if($what == ‘test‘){            $what = ‘測試前通知類屬性截取 <br/>‘;        }        echo "$who 想要 $what ";    }}$testclass1 = new changeProperty();$testpoint2 = function  ( AopJoinPoint $aop_tjp ) use( $testclass1 ){    if ( $aop_tjp->getKindOfAdvice() === AOP_KIND_BEFORE_READ_PROPERTY )    {        return; // 如果屬性不能讀則返回    }    elseif ( $aop_tjp->getKindOfAdvice() === AOP_KIND_BEFORE_WRITE_PROPERTY )    {        $testclass1->shoot($aop_tjp->getObject()->getName(),$aop_tjp->getAssignedValue());    }};//測試類別屬性aop_add_before(‘testClass2->publicProperty1‘, $testpoint2);

 

test.php源碼

<?phprequire ‘testaop.php‘;require ‘testclass.php‘;require ‘testfunction.php‘;header("Content-Type:text/html;charset=utf-8"); //前通知testFunc1();$testClass1 = new testClass1();echo $testClass1->testBeforAdd1();$runtest2 = new testClass2(‘skyboy‘);$runtest2->test();

 

執行test.php

這是前切點測試函數:aop_add_before 這是前切點測試類別方法:testClass1skyboy 想要 測試前通知類屬性截取 

 

返回後通知aop_add_after

在代碼中一些特殊點之後使用的通知,一般是調用一個方法或者函數。

測試函數

 testfunction.php源碼:

function testFunc2(){    echo ‘這是返回後通知測試:‘;}

testaop.php源碼:

//測試返回後通知$testpoint22 = function  (){    echo "aop_add_after <br/>";};aop_add_after(‘testFunc2()‘, $testpoint22);

test.php源碼:

//後通知testFunc2();

 

執行test.php

這是返回後通知測試:aop_add_after

  

類和類屬性和前通知類似,為了節省篇幅,這裡偷懶了。

 

周邊通知aop_add_around 測試函數

testfunction.php源碼:

function testFunc3($param1,$param2){    return $param1. $param2;}

 

testaop.php源碼:

//測試周邊通知function testaround (AopJoinPoint $object){    $args = $object->getArguments();    if ($args[0] !== null) {        $args[0] = ‘我想測試‘;    }    if ($args[1] !== null) {        $args[1] = ‘周邊通知:‘;    }    $object->setArguments($args);    $object->process();        $returnValue = $object->getReturnedValue();    $returnValue .= ‘aop_add_around<br/>‘;    $object->setReturnedValue($returnValue);    }aop_add_around(‘testFunc3()‘, ‘testaround‘);

 

test.php源碼:

//周邊通知echo testFunc3(1,2);

 

執行test.php

我想測試周邊通知:aop_add_around

 

 

類和類屬性和前通知類似。

 

aop-php函數說明

除了三個重要函數aop_add_before,aop_add_after,aop_add_around之外,我們還要記住這幾個重要的函數。

getKindOfAdvice

擷取通知的類型。有以下幾個預設值。一般用在方法的屬性更改。

• AOP_KIND_BEFORE before a given call, may it be function, method or property
• AOP_KIND_BEFORE_METHOD before a method call (method of an object)
• AOP_KIND_BEFORE_FUNCTION before a function call (not a method call)
• AOP_KIND_BEFORE_PROPERTY before a property (read or write)
• AOP_KIND_BEFORE_READ_PROPERTY before a property access (read only)
• AOP_KIND_BEFORE_WRITE_PROPERTY before a property write (write only)
• AOP_KIND_AROUND around a given call, may it be function, method or property access (read / write)
• AOP_KIND_AROUND_METHOD around a method call (method of an object)
• AOP_KIND_AROUND_FUNCTION around a function call (not a method call)
• AOP_KIND_AROUND_PROPERTY around a property (read or write)
• AOP_KIND_AROUND_READ_PROPERTY around a property access (read only)
• AOP_KIND_AROUND_WRITE_PROPERTY around a property write (write only)
• AOP_KIND_AFTER after a given call, may it be function, method or property access (read / write)
• AOP_KIND_AFTER_METHOD after a method call (method of an object)
• AOP_KIND_AFTER_FUNCTION after a function call (not a method call)
• AOP_KIND_AFTER_PROPERTY after a property (read or write)
• AOP_KIND_AFTER_READ_PROPERTY after a property access (read only)
• AOP_KIND_AFTER_WRITE_PROPERTY after a property write (write only)

getArguments

擷取方法的參數。一般用在aop_add_before/aop_add_around。

setArguments

設定方法的參數。一般用在aop_add_before/aop_add_around。

getReturnedValue

擷取方法的傳回值。一般用在aop_add_after/aop_add_around。

setReturnedValue

設定方法的傳回值。一般用在aop_add_after/aop_add_around。

process

讓方法運行。一般用在aop_add_around。

 

具體詳細說明,請參考官方文檔。

 

aop-php開啟和關閉

建立一個檔案aopopenclose.php

源碼如下:

<?phpini_set("aop.enable", "1");echo "aop is enabled<br />";function foo (){    echo "I‘m foo<br />";}$adviceShowFoo = function  (){    echo "After foo<br />";};aop_add_after(‘foo()‘, $adviceShowFoo);foo();ini_set(‘aop.enable‘, ‘0‘);echo "aop is now disabled<br />";foo();echo "But you can still register new aspects<br />";aop_add_after(‘f*()‘, $adviceShowFoo);foo();ini_set(‘aop.enable‘, ‘1‘);echo "Aop is now enabled<br />";foo();

 

運行結果:

aop is enabledI‘m fooAfter fooaop is now disabledI‘m fooAfter fooBut you can still register new aspectsI‘m fooAfter fooAfter fooAop is now enabledI‘m fooAfter fooAfter foo

  

aop-php總結

aop-php在真實意義上實現了php的aop,使用者無需用其他的方式即可輕鬆實現。aop的編程思想是一把利刃,可以讓耦合性差的項目輕鬆實現解耦。

全部測試檔案和編輯後檔案打包。點此下載。(基於ceotos環境php5.3編譯)

 

連結

 

php之aop實踐

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.