基于AspectJ就是基于@AspectJ注解,基于Schema就是全部依靠配置文件。那么首先要了解Java注解。
Java注解初探
在JDK5.0中,我们可以自定义标签,并通过Java语言的反射机制获取类中标注的注解,完成特定的功能。
注解不能直接干扰程序代码的运行,无论增加或者删除注解,代码都能够正常运行。
注解举例三步走:
第一步:定义注解和成员变量:
备注:
使用@interface修饰符定义注解类;
@Retention(…RUNTIME)表示该注解可以在运行期被JVM读取;
@Target(…METHOD)表示这个注解只能被用到目标类的方法上。
第二步:把注解和成员变量标注在目标方法上。
第三步:获取目标方法上所标注的注解对象,然后利用注解的成员变量为目标方法做一些事情。
基于AspectJ注解的AOP
有了前几篇关于增强、切面的例子和java注解的基础,用下面的例子便能清晰认识@AspectJ的用法。
第一步:目标类定义:
第二步:用@AspectJ定义一个切面
@Before是增强类型,还有许多:
- @Before,前置增强。
- @AfterReturning,后置增强。
- @Around,环绕增强。
- @AfterThrowing,抛出增强。
- @DeclareParents,引介增强。
第三步,用AspectJproxyFactory织入切面
第三步的Schema命名空间方式:
上例中切面的定义中beforeGreeting()方法没有任何入参,因此暂时无法访问目标连接点的信息。
上例中的execution(*greetTo(..))是切点表达式(函数),execution是关键字,后面是操作参数(入参)。
切点函数还有很多,可以大概了解一下:
类别 |
函数 |
入参 |
说明 |
方法切点函数 |
execution() |
方法 匹配模式串 |
表示满足某一匹配模式的所有目标类方法连接点。如execution(* greetTo(..))表示所有目标类中的greetTo()方法。 |
@annotation() |
方法注 解类名 |
表示标注了特定注解的目标方法连接点。如@annotation(com.baobaotao.anno.NeedTest)表示任何标注了@NeedTest注解的目标类方法。 |
|
方法入参切点函数 |
args() |
类名 |
通过判别目标类方法运行时入参对象的类型定义指定连接点。如args(com.baobaotao.Waiter)表示所有有且仅有一个按类型匹配于Waiter的入参的方法。 |
@args() |
类型注 解类名 |
通过判别目标方法的运行时入参对象的类是否标注特定注解来指定连接点。如@args(com.baobaotao.Monitorable)表示任何这样的一个目标方法:它有一个入参且入参对象的类标注@Monitorable注解。 |
|
目标类切点函数 |
within() |
类名匹配串 |
表示特定域下的所有连接点。如within(com.baobaotao.service.*)表示com.baobaotao.service包中的所有连接点,也即包中所有类的所有方法,而within(com.baobaotao.service.*Service)表示在com.baobaotao.service包中,所有以Service结尾的类的所有连接点。 |
target() |
类名 |
假如目标类按类型匹配于指定类,则目标类的所有连接点匹配这个切点。如通过target(com.baobaotao.Waiter)定义的切点,Waiter、以及Waiter实现类NaiveWaiter中所有连接点都匹配该切点。 |
|
@within() |
类型注解类名 |
假如目标类按类型匹配于某个类A,且类A标注了特定注解,则目标类的所有连接点匹配这个切点。 如@within(com.baobaotao.Monitorable)定义的切点,假如Waiter类标注了@Monitorable注解,则Waiter以及Waiter实现类NaiveWaiter类的所有连接点都匹配。 |
|
@target() |
类型注解类名 |
目标类标注了特定注解,则目标类所有连接点匹配该切点。如@target(com.baobaotao.Monitorable),假如NaiveWaiter标注了@Monitorable,则NaiveWaiter所有连接点匹配切点。 |
|
代理类切点函数 |
this() |
类名 |
代理类按类型匹配于指定类,则被代理的目标类所有连接点匹配切点。这个函数比较难理解,这里暂不举例,留待后面详解。 |
基于Schema配置切面(all in schema)