AOP-面向切面编程
——AspectJ
2016年3月23日
1 目标:在不改变原有程序的前题下,增加新的功能。
能够为类、方法、jar包等增加新功能。
能够为自己的程序增加新功能。
2 原理:使用aspectj代替java重新编译和组织已有的基本功能类。
参考:Aspectj Cookbook中文版。
aspectj将代码中的aspectj相关内容编译为标准java程序。
使用时将编译后的class文件部署到相应的路径使用。
2.1 aspectj脚本:用于构造aspectj程序的语言,OO,类似Java。
this:使用thisJoinPoint作为aspectj中代理对象的this。由于切入点的信息有些是静态的(如getClass(),getSignature()等),可以使用thisJoinPoitStaticPart直接获取。
3 流程:创建Aspectj工程,创建Java 业务,使用Apsectj扩展原Java业务。
3.1 安装Aspect支持库
下载aspectj.jar,解压后,将lib中的jar复制到工程的lib文件夹中,将jar加入到classpath。
3.2 创建Aspectj工程:File->new->Aspectj Project。
3.3 创建Java业务:创建普通的Java应用。
//ISum.java
package lee;
public interface ISum {
public int sum(int a,int b);
}
//Sum.java
package lee;
public class Sum implementsISum {
publicSum() {
super();
// TODO Auto-generated constructor stub
System.out.println("create a lee.Sum object.");
}
}
//Main.java
package lee;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sum s=new Sum();
s.sum();
}
}
3.4 使用Aspect扩展原Java业务:定义切入点,定义处理。
//TxAspect.aj
package lee;
public aspect TxAspect {
pointcutmyPC():call(void Sum.sum());
before():myPC(){
System.out.println("before():myPC()");
}
}
//结果
create a lee.Sum object.
before():myPC()
Sum.sum()
4 方法:AOP概念和配置
4.1 基本概念:aspect,pointcut,joinpoint,advice
连接点JoinPoint:原程序中具体需要被影响的函数、类、对象等位置点。
切入点pointcut:Aspectj对连接点的定义。具体指一个函数调用时机,可以设置多个,如servlet的url。可以在此切入点设置各种处理。
处理Advice:对切入点进行各种操作。可以在切入点之前、之后等多种时机设置处理。
参数arg-names:连接点的实参,可以在这里指定名称。
切面aspect:一个具体的工作流单位。其中包括切入点,各个切入点对应的处理。
参考:http://blog.csdn.net/zuyi532/article/details/7992323
http://blog.csdn.net/awangz/article/details/7750081
http://blog.csdn.net/wangpeng047/article/details/8556800
4.2 AspectJ语法
4.2.1切入点定义:pointcut。
4.2.1.1 函数调用:pointcut 名称(参数类型 值,…):call(权限 返回值 方法(参数类型列表))
4.2.1.2 带参数的函数调用:pointcut 名称(参数类型 值,…):call(权限 返回值 方法(参数类型列表))&&args(参数值列表)
pointcut myRPC(int a, intb):call(public int Sum.sum(int,int))&&args(a,b);
4.2.1.3 获取调用函数时的对象:pointcut 名称(调用者类型 值):call(权限 返回值 方法(参数类型列表)) &&target(调用者值)
pointcut myTPC(Summ):call(void Sum.sum())&&target(m);
4.2.1.4 函数调用(类内部上下文):pointcut 名称(参数类型 值,…):execution(权限 返回值 方法(参数类型列表))
pointcutmyPCE():execution(void Sum.sum());
4.2.1.5 函数调用(类内部上下文)并显示获取this对象:pointcut 名称(类型 值):execution(权限 返回值 方法(参数类型列表))&&this(值)
pointcut myPCET(ISummySum):execution(void Sum.sum())&&this(mySum);
4.2.2切入点调用:处理advice。
4.2.2.1 调用前before():pointcut。
before():myPC(){…}
4.2.2.2 调用后after() returning(返回类型 值):pointcut。
after(int a,int b)returning(int rtn):myRPC(a,b){…}
4.2.2.3 指定调用时机around():必须指定返回值类型。使用proceed()调用原函数。around()将生成一个override函数替换原函数,因此返回值类型必须相容。
返回值类型around(参数):pointcut
int around(int a,intb):myRPC(a,b){…}
4.2.2.4 示例:before()和after()调用
//ISum.java
package lee;
public interface ISum {
public int sum(int a,int b);
}
//Sum.java
package lee;
public class Sum implementsISum {
public Sum() {
super();
// TODO Auto-generated constructor stub
System.out.println("create a lee.Sum object.");
}
void sum(){
System.out.println("Sum.sum()");
}
@Override
public int sum(int a, int b) {
// TODO Auto-generated method stub
System.out.println("lee.Sum.sum(int a,int b).");
return a+b;
}
}
//Main.java
package lee;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sum s=new Sum();
s.sum();
System.out.println("s.sum(3,5)="+s.sum(3,5));
}
}
//TxAspect.aj
package lee;
public aspect TxAspect {
pointcutmyPC():call(void Sum.sum());
before():myPC(){
System.out.println("before():myPC()");
}
after():myPC(){
System.out.println("after():myPC()&#