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 enabled I'm foo After foo aop is now disabled I'm foo After foo But you can still register new aspects I'm foo After foo After foo Aop is now enabled I'm foo After foo After 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 其实在之前的源码解读里面,关于织入的部分并没有说清楚,那些前置.后 ...
随机推荐
- Robot Framework--10 万能的evaluate
转自:http://blog.csdn.net/tulituqi/article/details/10124559 这一讲我们重点来介绍一下一个常用的关键字evaluate. 我觉得这个关键字在RF里 ...
- awk操作数组注意几点
awk的数组跟其他程序设计语言的数组有所不同:1.可以直接在awk中定义数组:2.数组元素的初始值为0或空字符串,除非他们被显示的指定初始化:3.数组可以自动扩展:4.都是关联数组,数字下标也会转成字 ...
- Description DisplayName Display的关系
Description DisplayName Display的关系 ?
- Google Guava14.0 瓜娃学习笔记
Guava 是java api的增强与扩展,提供复杂的java 数据结构,使你的代码更简短精炼,具有良好的可读性.看看guava给我们提供了哪些很酷的功能: 集合创建: Map<String, ...
- linux 下 zip unzip压缩与解压
注:*压缩成限.zip格式文件 常用解压缩: [root@mysql test]# unzip -o test.zip -d tmp/ 将压缩文件test.zip在指定目录tmp下解压缩,如果已有相同 ...
- Nginx + spawn-fcgi- Ubuntu中文
Nginx - Ubuntu中文 页面 讨论 查看源代码 历史 导航 首页 最近更改 随机页面 页面分类 帮助 编辑 编辑指南 沙盒 新闻动态 字词处理 工具 链入页面 相关更改 特殊页面 打印版 ...
- xStream完美转换XML、JSON
xStream框架 xStream可以轻易的将Java对象和xml文档相互转换,而且可以修改某个特定的属性和节点名称,而且也支持json的转换: 前面有介绍过json-lib这个框架,在线博文:htt ...
- linuxMint install shuruma
http://my.oschina.net/u/1446273/blog/306053 http://blog.sina.com.cn/s/blog_5d406a1b0101jlgn.html htt ...
- Hadoop之HDFS文件操作常有两种方式(转载)
摘要:Hadoop之HDFS文件操作常有两种方式,命令行方式和JavaAPI方式.本文介绍如何利用这两种方式对HDFS文件进行操作. 关键词:HDFS文件 命令行 Java API HD ...
- CF467C George and Job (DP)
Codeforces Round #267 (Div. 2) C. George and Job time limit per test 1 second memory limit per test ...