php之aop实践
aop简介
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。
aop-php简介
AOP-PHP是一个PECL扩展,您可以在PHP中使用面向方面的编程,无需编译或进行其他任何中间步骤。
AOP扩展的设计是最简单的方法,你可以认为PHP中的aop实现。
AOP旨在让横切关注点的分离(缓存,日志,安全,交易,……)
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
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的一些专业术语。
参考文档
准备文件
在实践之前我们需要准备四个文件:测试函数文件testfunction.php、测试类文件testclass.php、测试aop文件testaop.php和运行文件test.php。
这样做可以真实模拟我们的项目,大部分的项目都是这样布局的。
aop-php实践之通知
前通知aop_add_before
在代码中一些特殊点之前使用的通知,正常是调用一个方法或者函数。
我们先测试函数
testfunction.php代码:
<?php
function testFunc1(){
echo 'aop_add_before <br/>';
}
testaop.php代码:
<?php
$testpoint1 = function () {
echo "这是前切点测试函数:";
};
aop_add_before('testFunc1()', $testpoint1);
test.php代码:
<?php
require 'testaop.php';
require 'testclass.php';
require 'testfunction.php';
header("Content-Type:text/html;charset=utf-8");
testFunc1();
不出意外,执行test.php我们将会看到:
这是前切点测试函数:aop_add_before
我们再玩哈类
testclass.php代码:

<?php
class 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代码:

<?php
require '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源码

<?php
require '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
这是前切点测试类方法:testClass1
skyboy 想要 测试前通知类属性截取
返回后通知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
源码如下:

<?php
ini_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实践的更多相关文章
- Spring入门之AOP实践:@Aspect + @Pointcut + @Before / @Around / @After
零.准备知识 1)AOP相关概念:Aspect.Advice.Join point.Pointcut.Weaving.Target等. ref: https://www.cnblogs.com/zha ...
- Method Swizzling 和 AOP 实践(转)
上一篇介绍了 Objective-C Messaging.利用 Objective-C 的 Runtime 特性,我们可以给语言做扩展,帮助解决项目开发中的一些设计和技术问题.这一篇,我们来探索一些利 ...
- Spring基础系列--AOP实践
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9615720.html 本文目的是简单讲解下Spring AOP的使用. 推荐使用IDEA ...
- spring aop 实践
之前用的ssm框架,大部分只是利用spring的IOC特性,很明显这能够为我们开发人员在对象的创建上面节省大部分时间.当相似得到业务越来越多,很多代码也是越来越重复,轮子是越来越重复,比如验证用户登录 ...
- AOP实践--利用MVC5 Filter实现登录状态判断
AOP有的翻译"面向切面编程",有的是"面向方面编程".其实名字不重要,思想才是核心,mvc的Filter让我们很 方便达到这种面向方面编程,就是在现有代码的基 ...
- [置顶]
Android AOP 实践笔记
本文同步自wing的地方酒馆 最近博客更新越来越慢了,有两方面原因: 1.没啥好写的. 2.应该沉下心好好沉淀自己,积累一些东西,博客写的太频繁有"刷博客"之嫌,还容易浮躁. 浮躁 ...
- AOP实践—ASP.NET MVC5 使用Filter过滤Action参数防止sql注入,让你代码安全简洁
在开发程序的过程中,稍微不注意就会隐含有sql注入的危险.今天我就来说下,ASP.NET mvc 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁.不用每下地方对参数的值都进行检 ...
- [转载]AOP面向方面编程
1.引言 软件开发的目标是要对世界的部分元素或者信息流建立模型,实现软件系统的工程需要将系统分解成可以创建和管理的模块.于是出现了以系统模块化特性的面向对象程序设计技术.模块化的面向对象编程极度极地提 ...
- Spring基础系列--AOP织入逻辑跟踪
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9619910.html 其实在之前的源码解读里面,关于织入的部分并没有说清楚,那些前置.后 ...
随机推荐
- Yii rules常用规则(转)
public function rules() { return array( //必须填写 array('email, username, password,agree,verifyPassword ...
- Oracle nvl(),nvl2()函数介绍
NVL函数 Oracle/PLSQL中的一个函数. 格式为: NVL( string1, replace_with) 功能:如果string1为NULL,则NVL函数返回replace_with的值, ...
- html页面 代码 编写的 一些 基本素养 约定 知识点
hmtl代码书写也要养成一段一段的 区块代码, 每个区块代码 进行 html的 功能注释 自由文字的获得: (lorem ipsum: 乱数假文, 哑元文字) lorem ipsum: lipsum等 ...
- PHP CLI下接受参数的几种方法
PHP CLI(命令行模式下)接受参数有多种方法: (1)使用$argv接受参数 <?php //变量仅在 register_argc_argv 打开时可用. print_r($argc); / ...
- 一次关于使用status作为变量引发的bug及思考
这个bug出现在一年前,当时自己大学还没毕业,刚刚进入一家公司实习.那个时候还没有用seajs或者requirejs那样的模块化管理的库,也没有用一个自执行的函数将要执行的代码包裹起来,于是bug就在 ...
- 终端下使用cocopods
http://blog.csdn.net/showhilllee/article/details/38398119
- 文件操作 fopen() fclose()
#define _CRT_SECURE_NO_DEPRECATE /*取消scanf,printf不安全之类的错误提示*/ /* fopen example */ #include <stdio ...
- mybatis 多个dao重名,根据namespace解析
在mybatis通过执行sql语句的方式是,用getSqlSession().xxx(param,..)方法来调用, 其中第一个参数就是dao mapper.xml文件的命名空间.id package ...
- Alice and Bob 要用到辗转相减
Alice and BobTime Limit: 1 Sec Memory Limit: 64 MBSubmit: 255 Solved: 43 Description Alice is a be ...
- C#操作Word的超详细总结
本文中用C#来操作Word,包括: 创建Word: 插入文字,选择文字,编辑文字的字号.粗细.颜色.下划线等: 设置段落的首行缩进.行距: 设置页面页边距和纸张大小: 设置页眉.页码: 插入图片,设置 ...