AspectJ语法示例及AOP基本概念

一.AOP概念

1.1通知(Advice)

前置通知(Before):在目标方法被调用之前调用通知功能;

后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;

返回通知(AfterReturning):在目标方法成功执行之后调用通知;

异常通知(AfterThrowing):在目标方法抛出异常后调用通知;

环绕通知(Around):通知报过了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

1.2连接点(Join point)

连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。(切点方法中配置的匹配的方法都是连接点)

1.3切点(Pointcut)

定义通知所要织入的一个或多个连接点。

1.4切面(Aspect)

是通知和切点的结合。

1.5引入(Introduction)

向现有的类添加新的方法和属性。

1.6织入(Weaving)

织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:

编译期:切面在目标类编译时被织入,这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。

类加载期:切面在目标类加载到jvm时被织入。这种方式 需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入(load-time weaving,LTW)就支持以这种方式织入切面。

运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态的创建一个代理对象。Spring AOP就是以这种方式织入切面的。

以上内容转载自:切面详解

二.Spring AOP支持的AspectJ切入点指示符

切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点

  • execution:用于匹配方法执行的连接点;

  • within:用于匹配指定类型内的方法执行;

  • this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;

  • target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;

  • args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;

  • @within:用于匹配所以持有指定注解类型内的方法;

  • @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;

  • @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;

  • @annotation:用于匹配当前执行方法持有指定注解的方法;

  • bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;

  • reference pointcut:表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。

AspectJ切入点支持的切入点指示符还有: call、get、set、preinitialization、staticinitialization、initialization、handler、adviceexecution、withincode、cflow、cflowbelow、if、@this、@withincode;但Spring AOP目前不支持这些指示符,使用这些指示符将抛出IllegalArgumentException异常。这些指示符Spring AOP可能会在以后进行扩展。

2.1 execution示例

execution:使用“execution(方法表达式)”匹配方法执行;

模式描述
public * *(…)任何公共方法的执行
* cn.javass…IPointcutService.*()cn.javass包及所有子包下IPointcutService接口中的任何无参方法
* cn.javass….(…)cn.javass包及所有子包下任何类的任何方法
* cn.javass…IPointcutService.()cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法
* (!cn.javass…IPointcutService+).*(…)非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法
* cn.javass…IPointcutService+.*()cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法
* cn.javass…IPointcut*.test*(java.util.Date)cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的。如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的;
* cn.javass…IPointcut*.test*(…) throws IllegalArgumentException, ArrayIndexOutOfBoundsExceptioncn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常
* (cn.javass…IPointcutService+&& java.io.Serializable+).*(…)任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法
@java.lang.Deprecated * *(…)任何持有@java.lang.Deprecated注解的方法
@java.lang.Deprecated @cn.javass…Secure * *(…)任何持有@java.lang.Deprecated和@cn.javass…Secure注解的方法
@(java.lang.Deprecated
(@cn.javass…Secure *) *(…)任何返回值类型持有@cn.javass…Secure的方法
* (@cn.javass…Secure ).(…)任何定义方法的类型持有@cn.javass…Secure的方法
* (@cn.javass…Secure () , @cn.javass…Secure (*))任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,如public void test(@Secure String str1,@Secure String str1);
* *((@ cn.javass…Secure ))或 *(@ cn.javass…Secure *)任何带有一个参数的方法,且该参数类型持有@ cn.javass…Secure;如public void test(Model model);且Model类上持有@Secure注解
* *(@cn.javass…Secure (@cn.javass…Secure *) ,@ cn.javass…Secure (@cn.javass…Secure *))任何带有两个参数的方法,且这两个参数都被@ cn.javass…
* *( java.util.Map<cn.javass…Model, cn.javass…Model> , …)任何带有一个java.util.Map参数的方法,且该参数类型是以< cn.javass…Model, cn.javass…Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“* *(java.util.HashMap<cn.javass…Model,cn.javass…Model>, …)”进行匹配;而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配
* *(java.util.Collection<@cn.javass…Secure *>)任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass…Secure注解; 如public void test(Collection collection);Model类型上持有@cn.javass…Secure
* *(java.util.Set<? extends HashMap>)任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型继承与HashMap;Spring AOP目前测试不能正常工作
* *(java.util.List<? super HashMap>)任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型是HashMap的基类型;如public voi test(Map map);Spring AOP目前测试不能正常工作
* (<@cn.javass…Secure *>)任何带有一个参数的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass…Secure注解;Spring AOP目前测试不能正常工作

2.2 within示例

使用“within(类型表达式)”匹配指定类型内的方法执行;

模式描述
within(cn.javass…*)cn.javass包及子包下的任何方法执行
within(cn.javass…IPointcutService+)cn.javass包或所有子包下IPointcutService类型及子类型的任何方法
within(@cn.javass…Secure *)持有cn.javass…Secure注解的任何类型的任何方法。必须是在目标对象上声明这个注解,在接口上声明的对它不起作用

2.3 this示例

使用“this(类型全限定名)”匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口方法也可以匹配;注意this中使用的表达式必须是类型全限定名,不支持通配符;

模式描述
this(cn.javass.spring.chapter6.service.IPointcutService)当前AOP对象实现了 IPointcutService接口的任何方法
this(cn.javass.spring.chapter6.service.IIntroductionService)当前AOP对象实现了 IIntroductionService接口的任何方法。可能是引入接口

2.4 target示例

使用“target(类型全限定名)”匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是类型全限定名,不支持通配符;

模式描述
target(cn.javass.spring.chapter6.service.IPointcutService)当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法
target(cn.javass.spring.chapter6.service.IIntroductionService)当前目标对象(非AOP对象) 实现了IIntroductionService 接口的任何方法。不可能是引入接口

2.5 args示例

使用“args(参数类型列表)”匹配当前执行的方法传入的参数为指定类型的执行方法;注意是匹配传入的参数类型,不是匹配方法签名的参数类型;参数类型列表中的参数必须是类型全限定名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用;

模式描述
args (java.io.Serializable,…)任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的

2.6 @within示例

使用“@within(注解类型)”匹配所以持有指定注解类型内的方法;注解类型也必须是全限定类型名;

模式描述
@within cn.javass.spring.chapter6.Secure)任何目标对象对应的类型持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用

2.7 @target示例

使用“@target(注解类型)”匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是全限定类型名;

模式描述
@target (cn.javass.spring.chapter6.Secure)任何目标对象持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用

2.8 @args示例

使用“@args(注解列表)”匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是全限定类型名;

模式描述
@args (cn.javass.spring.chapter6.Secure)任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符;

2.9 @annotation示例

使用“@annotation(注解类型)”匹配当前执行方法持有指定注解的方法;注解类型也必须是全限定类型名;

模式描述
@annotation(cn.javass.spring.chapter6.Secure )当前执行方法上持有注解 cn.javass.spring.chapter6.Secure将被匹配

2.10 bean示例

使用“bean(Bean id或名字通配符)”匹配特定名称的Bean对象的执行方法;Spring ASP扩展的,在AspectJ中无相应概念;

模式描述
bean(*Service)匹配所有以Service命名(id或name)结尾的Bean

2.11 reference pointcut示例

使用“target(类型全限定名)”匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是类型全限定名,不支持通配符;

模式描述
pointcut1 && pointcut2pointcut1和pointcut2分别是前面十个切入点指示符;表示要符合pointcut1和pointcut2的规则

三.JoinPoint

AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口,任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。

3.1 JoinPoint

提供访问当前被通知方法的目标对象、代理对象、方法参数等数据;

package org.aspectj.lang;  
import org.aspectj.lang.reflect.SourceLocation;  
public interface JoinPoint {  
    String toString();         //连接点所在位置的相关信息  
    String toShortString();     //连接点所在位置的简短相关信息  
    String toLongString();     //连接点所在位置的全部相关信息  
    Object getThis();         //返回AOP代理对象  
    Object getTarget();       //返回目标对象  
    Object[] getArgs();       //返回被通知方法参数列表  
    Signature getSignature();  //返回当前连接点签名  
    SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置  
    String getKind();        //连接点类型  
    StaticPart getStaticPart(); //返回连接点静态部分  
}  

3.2ProceedingJoinPoint

用于环绕通知,使用proceed()方法来执行目标方法;

public interface ProceedingJoinPoint extends JoinPoint {  
    public Object proceed() throws Throwable;  //执行目标方法
    public Object proceed(Object[] args) throws Throwable;  //用新的参数执行目标方法
}  

3.3JoinPoint.StaticPart

提供访问连接点的静态部分,如被通知方法签名、连接点类型等;

public interface StaticPart {
    Signature getSignature();    //返回当前连接点签名  
    String getKind();          //连接点类型  
    int getId();               //唯一标识  
    String toString();         //连接点所在位置的相关信息  
    String toShortString();     //连接点所在位置的简短相关信息  
    String toLongString();     //连接点所在位置的全部相关信息  
} 

第二部分内容以上内容转载自:Spring 之AOP AspectJ切入点语法详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值