您的位置:首页 > 编程语言 > Java开发

Spring AOP

2017-04-12 16:34 113 查看
AOP(Aspect Oriented Programming)面向切面编程,通过预编译方式和运行期动态代理实现程序功能的横向多模块统一控制的一种技术。AOP是OOP的补充,是spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP可以分为静态织入与动态织入,静态织入即在编译前将需织入内容写入目标模块中,这样成本非常高。动态织入则不需要改变目标模块。Spring框架实现了AOP,使用注解配置完成AOP比使用XML配置要更加方便与直观。



AOP 的相关概念

基本概念

连接点(Jointpoint) : 表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点,在AOP中表示为“在哪里干”;

切入点(Pointcut) :选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法,在AOP中表示为“在哪里干的集合”;

通知(Advice) : 在连接点上执行的行为,通知提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice),在Spring中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入通知;在AOP中表示为“干什么”;

方面/切面(Aspect) : 横切关注点的模块化,比如上边提到的日志组件。可以认为是通知、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现;在AOP中表示为“在哪干和干什么集合”;

引入(inter-type declaration) : 也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象), 在AOP中表示为“干什么(引入什么)”;

目标对象(Target Object) : 需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为“被通知对象”;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象,在AOP中表示为“对谁干”;

AOP代理(AOP Proxy) : AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。

织入(Weaving) : 织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行。

通知类型

前置通知(Before Advice) : 在切入点选择的连接点处的方法之前执行的通知,该通知不影响正常程序执行流程(除非该通知抛出异常,该异常将中断当前方法链的执行而返回)。

后置通知(After Advice) : 在切入点选择的连接点处的方法之后执行的通知,包括如下类型的后置通知:

后置返回通知(After returning Advice) : 在切入点选择的连接点处的方法正常执行完毕时执行的通知,必须是连接点处的方法没抛出任何异常正常返回时才调用后置通知。

后置异常通知(After throwing Advice) : 在切入点选择的连接点处的方法抛出异常返回时执行的通知,必须是连接点处的方法抛出任何异常返回时才调用异常通知。

后置最终通知(After finally Advice) : 在切入点选择的连接点处的方法返回时执行的通知,不管抛没抛出异常都执行,类似于Java中的finally块。

环绕通知(Around Advices) : 环绕着在切入点选择的连接点处的方法所执行的通知,环绕通知可以在方法调用之前和之后自定义任何行为,并且可以决定是否执行连接点处的方法、替换返回值、抛出异常等等。

AOP代理

AOP代理就是AOP框架通过代理模式创建的对象,Spring使用JDK动态代理或CGLIB代理来实现,Spring缺省使用JDK动态代理来实现,从而任何接口都可别代理,如果被代理的对象实现不是接口将默认使用CGLIB代理,不过CGLIB代理当然也可应用到接口。

AOP代理的目的就是将切面织入到目标对象。

基于Schema的AOP

基于Schema的AOP从Spring2.0之后通过“aop”命名空间来定义切面、切入点及声明通知。

在Spring配置文件中,所以AOP相关定义必须放在标签下,该标签下可以有< aop:pointcut>、< aop:advisor>、< aop:aspect>标签,配置顺序不可变。

< aop:pointcut>:用来定义切入点,该切入点可以重用;

< aop:advisor>:用来定义只有一个通知和一个切入点的切面;

< aop:aspect>:用来定义切面,该切面可以包含多个切入点和通知,而且标签内部的通知和切入点定义是无序的;和advisor的区别就在此,advisor只包含一个通知和一个切入点。



声明切面

切面就是包含切入点和通知的对象,在Spring容器中将被定义为一个Bean,Schema方式的切面需要一个切面支持Bean,该支持Bean的字段和方法提供了切面的状态和行为信息,并通过配置方式来指定切入点和通知实现。

切面使用标签指定,ref属性用来引用切面支持Bean。

切面支持Bean“aspectSupportBean”跟普通Bean完全一样使用,切面使用“ref”属性引用它。

声明切入点

1)在< aop:config>标签下使用< aop:pointcut>声明一个切入点Bean

该切入点可以被多个切面使用,对于需要共享使用的切入点最好使用该方式,该切入点使用id属性指定Bean名字,在通知定义时使用pointcut-ref属性通过该id引用切入点,expression属性指定切入点表达式:

<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.javass..*.*(..))"/>
<aop:aspect ref="aspectSupportBean">
<aop:before pointcut-ref="pointcut" method="before"/>
</aop:aspect>
</aop:config>


2)在标签下使用声明一个切入点Bean

该切入点可以被多个切面使用,但一般该切入点只被该切面使用,当然也可以被其他切面使用,但最好不要那样使用,该切入点使用id属性指定Bean名字,在通知定义时使用pointcut-ref属性通过该id引用切入点,expression属性指定切入点表达式:

<aop:config>
<aop:aspect ref="aspectSupportBean">
<aop:pointcut id=" pointcut" expression="execution(* cn.javass..*.*(..))"/>
<aop:before pointcut-ref="pointcut" method="before"/>
</aop:aspect>
</aop:config>


3)匿名切入点Bean

可以在声明通知时通过pointcut属性指定切入点表达式,该切入点是匿名切入点,只被该通知使用:

<aop:config>
<aop:aspect ref="aspectSupportBean">
<aop:after pointcut="execution(* cn.javass..*.*(..))" method="afterFinallyAdvice"/>
</aop:aspect>
</aop:config>


声明通知

前置通知

在切入点选择的方法之前执行,通过< aop:aspect>标签下的< aop:before>标签声明:

<aop:before pointcut="切入点表达式"  pointcut-ref="切入点Bean引用"
method="前置通知实现方法名"
arg-names="前置通知实现方法参数列表参数名字"/>


pointcut pointcut-ref :二者选一,指定切入点;

method:指定前置通知实现方法名,如果是多态需要加上参数类型,多个用“,”隔开,如beforeAdvice(java.lang.String);

arg-names :指定通知实现方法的参数名字,多个用“,”分隔,可选,类似于【3.1.2 构造器注入】中的参数名注入限制:在class文件中没生成变量调试信息是获取不到方法参数名字的,因此只有在类没生成变量调试信息时才需要使用arg-names属性来指定参数名,如arg-names=”param”表示通知实现方法的参数列表的第一个参数名字为“param”。

后置返回通知

在切入点选择的方法正常返回时执行,通过< aop:aspect>标签下的< aop:after-returning>标签声明:

<aop:after-returning pointcut="切入点表达式"  pointcut-ref="切入点Bean引用"
method="后置返回通知实现方法名"
arg-names="后置返回通知实现方法参数列表参数名字"
returning="返回值对应的后置返回通知实现方法参数名"
/>


pointcutpointcut-ref:同前置通知同义;

method:同前置通知同义;

arg-names:同前置通知同义;

returning:定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法执行正常返回后,将把目标方法返回值传给通知方法;returning限定了只有目标方法返回值匹配与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值。

后置异常通知

在切入点选择的方法抛出异常时执行,通过< aop:aspect>标签下的< aop:after-throwing>标签声明:

<aop:after-throwing pointcut="切入点表达式"  pointcut-ref="切入点Bean引用"
method="后置异常通知实现方法名"
arg-names="后置异常通知实现方法参数列表参数名字"
throwing="将抛出的异常赋值给的通知实现方法参数名"/>


pointcutpointcut-ref:同前置通知同义;

method:同前置通知同义;

arg-names:同前置通知同义;

throwing:定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;throwing限定了只有目标方法抛出的异常匹配与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。

后置最终通知

在切入点选择的方法返回时执行,不管是正常返回还是抛出异常都执行,通过< aop:aspect>标签下的< aop:after >标签声明:

<aop:after pointcut="切入点表达式"  pointcut-ref="切入点Bean引用"
method="后置最终通知实现方法名"
arg-names="后置最终通知实现方法参数列表参数名字"/>


pointcutpointcut-ref:同前置通知同义;

method:同前置通知同义;

arg-names:同前置通知同义;

环绕通知

环绕着在切入点选择的连接点处的方法所执行的通知,环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值,可通过< aop:aspect>标签下的< aop:around >标签声明:

<aop:around pointcut="切入点表达式"  pointcut-ref="切入点Bean引用"
method="后置最终通知实现方法名"
arg-names="后置最终通知实现方法参数列表参数名字"/>


pointcutpointcut-ref:同前置通知同义;

method:同前置通知同义;

arg-names:同前置通知同义;

引入

Spring引入允许为目标对象引入新的接口,通过在< aop:aspect>标签内使用< aop:declare-parents>标签进行引入,定义方式如下:

<aop:declare-parents
types-matching="AspectJ语法类型表达式"
implement-interface=引入的接口"
default-impl="引入接口的默认实现"
delegate-ref="引入接口的默认实现Bean引用"/>


types-matching:匹配需要引入接口的目标对象的AspectJ语法类型表达式;

implement-interface:定义需要引入的接口;

default-impldelegate-ref:定义引入接口的默认实现,二者选一,default-impl是接口的默认实现类全限定名,而delegate-ref是默认的实现的委托Bean名;

Advisor

Advisor表示只有一个通知和一个切入点的切面,由于Spring AOP都是基于AOP联盟的拦截器模型的环绕通知的,所以引入Advisor来支持各种通知类型(如前置通知等5种),Advisor概念来自于Spring1.2对AOP的支持,在AspectJ中没有相应的概念对应。

Advisor可以使用标签下的标签定义:

<aop:advisor pointcut="切入点表达式" pointcut-ref="切入点Bean引用"
advice-ref="通知API实现引用"/>


pointcutpointcut-ref:二者选一,指定切入点表达式;

advice-ref:引用通知API实现Bean,如前置通知接口为MethodBeforeAdvice;

基于@AspectJ的AOP

启用对@AspectJ的支持

Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:

<aop:aspectj-autoproxy/>


声明切面

@AspectJ风格的声明切面非常简单,使用@Aspect注解进行声明:

@Aspect()
Public class Aspect{ ……  }


声明切入点

@AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必须是返回void类型)实现。

@Pointcut(value="切入点表达式", argNames = "参数名列表")
public void pointcutName(……) {}


value :指定切入点表达式;

argNames:指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。

pointcutName:切入点名字,可以使用该名字进行引用该切入点表达式。

声明通知

前置通知

使用org.aspectj.lang.annotation 包下的@Before注解声明;

@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")


value:指定切入点表达式或命名切入点;

argNames:与Schema方式配置中的同义。

后置返回通知

使用org.aspectj.lang.annotation 包下的@AfterReturning注解声明;

@AfterReturning(
value="切入点表达式或命名切入点",
pointcut="切入点表达式或命名切入点",
argNames="参数列表参数名",
returning="返回值对应参数名")
/>


value:指定切入点表达式或命名切入点;

pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;

argNames:同前置通知同义;

returning:定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法执行正常返回后,将把目标方法返回值传给通知方法;returning限定了只有目标方法返回值匹配与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值。

后置异常通知

使用org.aspectj.lang.annotation 包下的@AfterThrowing注解声明;

@AfterThrowing (
value="切入点表达式或命名切入点",
pointcut="切入点表达式或命名切入点",
argNames="参数列表参数名",
throwing="异常对应参数名")


value:指定切入点表达式或命名切入点;

pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;

argNames:同前置通知同义;

throwing:定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;throwing限定了只有目标方法抛出的异常匹配与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。

后置最终通知

使用org.aspectj.lang.annotation 包下的@After注解声明;

@After (
value="切入点表达式或命名切入点",
argNames="参数列表参数名")


value:指定切入点表达式或命名切入点;

argNames:同前置通知同义;

环绕通知

使用org.aspectj.lang.annotation 包下的@Around注解声明;

@Around (
value="切入点表达式或命名切入点",
argNames="参数列表参数名")


value:指定切入点表达式或命名切入点;

argNames:同前置通知同义;

引入

@AspectJ风格的引入声明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents声明:

@DeclareParents(
value=" AspectJ语法类型表达式",
defaultImpl=引入接口的默认实现类)
private Interface interface;


value:匹配需要引入接口的目标对象的AspectJ语法类型表达式;与Schema方式中的types-matching属性同义;

defaultImpl:指定引入接口的默认实现类,没有与Schema方式中的delegate-ref属性同义的定义方式;

private Interface interface:指定需要引入的接口;

AspectJ

AspectJ切入点指示符

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可能会在以后进行扩展。

命名及匿名切入点

命名切入点可以被其他切入点引用,而匿名切入点是不可以的。

只有@AspectJ支持命名切入点,而Schema风格不支持命名切入点。

AspectJ类型匹配的通配符

* : 匹配任何数量字符;

.. : (两个点)匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。

+ : 匹配指定类型的子类型;仅能作为后缀放在类型模式后边。

示例解释
java.lang.String匹配String类型;
java.*.String匹配java包下的任何“一级子包”下的String类型;
如匹配java.lang.String,但不匹配java.lang.ss.String
java..*匹配java包及任何子包下的任何类型;
如匹配java.lang.String、java.lang.annotation.Annotation
java.lang.*ing匹配任何java.lang包下的以ing结尾的类型;
java.lang.Number+匹配java.lang包下的任何Number的自类型;
如匹配java.lang.Integer,也匹配java.math.BigInteger

组合切入点表达式

AspectJ使用 且(&&)、或(||)、非(!)来组合切入点表达式。

在Schema风格下,由于在XML中使用“&&”需要使用转义字符“&&”来代替之,所以很不方便,因此Spring ASP 提供了and、or、not来代替&&、||、!。

切入点使用示例

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注解的方法
(@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..Secure标记了;且这两个参数的类型上都持有@ cn.javass..Secure;
* *(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 map, String str);将不匹配,必须使用“* *(java.util.HashMap, ..)”进行匹配;
而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目前测试不能正常工作
within:使用“within(类型表达式)”匹配指定类型内的方法执行;

模式描述
within(cn.javass..*)cn.javass包及子包下的任何方法执行
within(cn.javass..IPointcutService+)cn.javass包或所有子包下IPointcutService类型及子类型的任何方法
within(@cn.javass..Secure *)持有cn.javass..Secure注解的任何类型的任何方法
必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
this:使用“this(类型全限定名)”匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口方法也可以匹配;注意this中使用的表达式必须是类型全限定名,不支持通配符;

模式描述
this(cn.javass.spring.chapter6.service.IPointcutService)当前AOP对象实现了 IPointcutService接口的任何方法
this(cn.javass.spring.chapter6.service.IIntroductionService)当前AOP对象实现了IIntroductionService接口的任何方法
也可能是引入接口
target:使用“target(类型全限定名)”匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是类型全限定名,不支持通配符;

模式描述
target(cn.javass.spring.chapter6.service.IPointcutService)当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法
ttarget(cn.javass.spring.chapter6.service.IIntroductionService)当前目标对象(非AOP对象) 实现了IIntroductionService 接口的任何方法
不可能是引入接口
args:使用“args(参数类型列表)”匹配当前执行的方法传入的参数为指定类型的执行方法;注意是匹配传入的参数类型,不是匹配方法签名的参数类型;参数类型列表中的参数必须是类型全限定名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用;

模式描述
args (java.io.Serializable,..)任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的
@within:使用“@within(注解类型)”匹配所以持有指定注解类型内的方法;注解类型也必须是全限定类型名;

模式描述
@within cn.javass.spring.chapter6.Secure)任何目标对象对应的类型持有Secure注解的类方法;
必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
@target:使用“@target(注解类型)”匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是全限定类型名;

模式描述
@target (cn.javass.spring.chapter6.Secure)任何目标对象持有Secure注解的类方法;
必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
@args:使用“@args(注解列表)”匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是全限定类型名;

模式描述
@args (cn.javass.spring.chapter6.Secure)任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符;
@annotation:使用“@annotation(注解类型)”匹配当前执行方法持有指定注解的方法;注解类型也必须是全限定类型名;

模式描述
@annotation(cn.javass.spring.chapter6.Secure )当前执行方法上持有注解 cn.javass.spring.chapter6.Secure将被匹配
bean:使用“bean(Bean id或名字通配符)”匹配特定名称的Bean对象的执行方法;Spring ASP扩展的,在AspectJ中无相应概念;

模式描述
bean(*Service)匹配所有以Service命名(id或name)结尾的Bean
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: