基于@AspectJ和schema的aop(二)---@AspectJ基础语法
@AspectJ使用jdk5.0和正规的AspectJ切点表达式描述切面, 由于spring只支持方法的连接点,所以Spring只支持部分AspectJ的切点语言.
1.切点表达式函数
AspectJ 5的切点表达式有关键字和操作参数组成,如execution(* greetTo(..))的切点表达式, execution为关键字, "* greetTo(..)"为操作参数.在这里execution表示目标类执行某一方法, 而"* greetTo(..)"描述目标方法的匹配模式, 两者联合起来表示目标类greetTo()方法的连接点.为了描述方便, 将execution()称作为函数, 而将匹配串"* greetTo(..)"称为函数的入参.
Spring支持9个@AspectJ切点表达式函数, 它们用不同的方式描述目标类的连接点.根据描述对象的不同, 可以大致分为4种类型.
- 方法切点函数: 通过描述目标类方法信息定义连接点
- 方法入参切点函数: 通过描述目标类方法的入参信息定义连接点
- 目标类切点函数: 通过描述目标类类型信息定义连接点
- 代理类切点函数: 通过描述目标类的代理类的信息定义连接点.
这四种类型的切点函数, 通过下表进行详细说明:
| 类别 | 函数 | 入参 | 说明 |
| 方法切点函数 | execution() | 方法匹配模式 | 表示满足某一模式的所有目标类方法连接点, 如execution(* greetTo(..))表示所有目标类中的greetTo()方法 |
| @annotation() | 方法注解类名 | 表示标注了特定注解的目标方法连接点, 如@annotation(com.bao.bao.aop.NeedTest)表示任何标注了@NeedTest注解的目标类方法 | |
| 方法入参切点函数 |
args() | 类名 | 通过判断目标类方法运行时入参对象的类型定义指定连接点.如args(com.bao.bao.Waiter)表示所有有且仅有一个按类型匹配于Waiter入参的方法 |
| @args() | 类型注解类名 | 通过判断目标方法运行时入参对象的类型是否标注特定注解来指定连接点, 如@args(com.bao.bao.Monitorable)表示任何这样的一个目标方法, 它有一个入参且入参对象的类标注了@Monitorable注解 | |
| 目标类切点函数 | within() | 类名匹配器 | 表示特定域下的所有连接点.如within(co.bao.bao.service.*)表示com.bao.bao.service包中的所有连接点.即包中所有的类的所有方法, 而within(com.bao.bao.service.*Service)表示在com.bao.bao.service包中所有以Service结尾的类的所有连接点 |
| target() | 类名 | 假如目标类按类型匹配于指定类, 则目标类的所有连接点匹配这个切点, 如通过target(com.bao.bao.Waiter)定义的切点, Waiter以及Waiter实现类NaiveWaiter中所有连接点都匹配该切点 | |
| @within() | 类型注解类名 | 假如目标类按类型匹配于某个类A, 且类A标注了特定注解,则目标类的所有连接点匹配这个切点.如@within(com.bao.bao.Monitorable)定义的切点, 假如Waiter类标注了@Monitorable注解, 则Waiter以及Waiter实现类NaiveWaiter类的所有连接点都匹配 | |
| @target() | 类型注解类名 | 目标类标注了特定注解, 则目标类所有连接点匹配该切点, 如@target(com.bao.bao.Monitorable).假如NaiveWaiter标注了@Monitorable, 则NaiveWaiter所有连接点匹配切点 | |
| 代理类切点函数 | this() | 类名 | 代理类按类型匹配于指定类, 则被代理的目标类所有连接点匹配切点. |
2.在函数入参中使用通配符
有些函数的入参可以接受通配符, @AspectJ支持3种通配符:
(1) * :匹配任意字符, 但它只能匹配上下文中的一个元素.
(2) ... : 匹配任意字符,可以匹配上下文中的多个元素, 但在表示类时, 必须和*联合使用, 而在表示入参时则单独使用.
(3) + :表示按类型匹配指定类的所有类, 必须跟在类名后面, 如com.bao.bao.Waiter+.继承或者扩展指定类的所有类, 同时还包括指定类本身.
@AspectJ函数按其是否支持通配符及支持的程度, 可以分成3类:
(1)支持所有通配符: execution(), within(), 如within(com.bao.bao.*), within(com.bao.bao.service.*Service+)等.
(2)仅支持+通配符: args(), this(), target(), 如args(com.bao.bao.Waiter+), target(java.util.List+)等.虽然这三个函数支持+通配符, 但是意义不大,因为对于这些函数来说, 使用和不适用+都是一样的.如target(com.bao.bao.Waiter)和targt(com.bao.bao.Waiter+)是等价的.
(3).不支持通配符:@args(), @within(), @target(), @annotation().如@args(com.bao.bao.NeedTest)和@within(com.bao.bao.NeedTest).
3.逻辑运算符
切点表达式由切点函数组成, 切点函数之间可以进行逻辑运算, 组成复合切点, Spring支持以下的切点运算符:
(1) && 与操作符:相当于切点的交集运算, 如果在Spring的xml配置文件中使用切点表达式, 由于&是xml特殊字符, 所以使用转义字符&&表示.为了使用方便, Spring提供了一个等效的运算符"and".如within(com.bao.bao..*) and args(String)表示在com.bao.bao包下所有类(当前包以及子孙包)拥有一个String入参的方法.
(2) || 或操作符, 相当于切点额并集运算, or是等效的操作符
(3) ! 非操作符: 相当于切点的反集运算, not是等效的操作符.
4.不同增强类型
在前面, 我们使用不同的接口描述各种增强,@AspectJ也为各种的增强类型提供了不同的注解类, 它们位于org.aspectj.lang.annotation.*包中, 这些注解类型拥有若干个成员,可以通过这些成员完成定义切点信息, 绑定连接点参数等操作.这些注解的存留期限都是RetentionPolicy.RUNTIME, 标注目标都是ElementType.METHOD.下面我们看下@AspectJ提供的几个增强注解.
(1) @Before
前置增强, 相当于BeforeAdvice的功能
(2) @AfterReturning
后置增强, 相当于AfterReturningAdvice的功能
(3) @Around
环绕增强, 相当于MethodInterceptor
(4) @AfterThrowing
抛出增强,相当于ThrowsAdvice
(5) @After
final增强,该增强没有对应的接口,但是可以把该增强看做是AfterReturningAdvice和ThrowsAdvice的混合物
(6) @DeclareParents
引介增强,相当于IntroductionInterceptor
下面给出引介增强的使用例子:
package com.bao.bao.aspectj;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
/**
* Created by xinfengyao on 16-10-24.
*/
@Aspect
public class EnableSellerAspect {
//为NaiveWaiter添加接口实现, 默认的实现类是SmartSeller
@DeclareParents(value = "com.bao.bao.aspectj.NaiveWaiter", defaultImpl = SmartSeller.class)
//要实现的接口
public Seller seller;
}
<bean id="waiter" class="com.bao.bao.aspectj.NaiveWaiter"/>
<bean class="com.bao.bao.aspectj.EnableSellerAspect"/>
<aop:aspectj-autoproxy/>
String config = "spring/spring-aspectj.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(config);
Waiter waiter = (Waiter) context.getBean("waiter");
waiter.serveTo("tom");
Seller seller = (Seller) waiter;
seller.sell("book");
运行结果:
NaiveWaiter serveTo tom... smartSeller sell goods
可见, NaiveWaiter已经成功地新增了Seller接口的实现
基于@AspectJ和schema的aop(二)---@AspectJ基础语法的更多相关文章
- 基于@AspectJ和schema的aop(四)---@AspectJ进阶
@AspectJ可以使用切点函数定义切点, 我们还可以使用逻辑运算对切点进行复合运算得到复合的切点. 我们还可以对切点进行命名, 从而可以复用切点.当一个连接点匹配多个切点时, 需要考虑增强织入的顺序 ...
- 基于@AspectJ和schema的aop(一)
在前面我们使用Pointcut和Advice描述切点和增强, 并使用Advisor整合两者描述切面.@AspectJ使用注解来描述切点和增强.两者使用的方式不同, 但是在本质上都是一样的. 我们还是用 ...
- spring3: schema的aop与Aspectj的aop的区别
schema的aop如下: 接口: package chapter6.service; public interface IHelloAroundService { public void sayAr ...
- 零基础学习JavaSE(二)——基础语法
二.Java 基础语法 2.1 Java 基础语法 java是一个面向对象的程序语言,及可把一切事物当做对象处理,而java的事物中最小的就是class (类),类中有方法,类可以创建对象,并且有一些 ...
- (spring-第19回【AOP基础篇】)基于AspectJ和Schema的AOP
基于AspectJ就是基于@AspectJ注解,基于Schema就是全部依靠配置文件.那么首先要了解Java注解. Java注解初探 在JDK5.0中,我们可以自定义标签,并通过Java语言的反射机制 ...
- 基于@AspectJ和schema的aop(三)---切点函数详解
切点函数是AspectJ表达式语言的核心, 也是使用@AspectJ进行切面定义的难点.本小节我们通过具体的实例对切点函数进行深入学习. 1.@annotation() @annotation()表示 ...
- MVC学习二:基础语法
目录 一:重载方法的调用 二:数据的传递 三:生成控件 四:显示加载视图 五:强类型视图 六:@Response.Write() 和 @Html.Raw()区别 七:视图中字符串的输入 八:模板页 一 ...
- Java基础学习笔记二 Java基础语法
注释 注释用来解释和说明程序的文字,注释是不会被执行的. 单行注释 //这是一条单行注释 public int i; 多行注释 /* 这是 * 一段注释, * 它跨越了多个行 */ public vo ...
- Scala(二)——基础语法(与Java的区分)和函数式编程
Scala快速入门(二) 一.键盘输入 关于基本类型的运算,以及复制运算,条件运算,运算符等知识,均和Java语言一样,这里不过多叙述. val name = StdIn.readLine() Std ...
随机推荐
- PostgreSQL中字符串相关问题
PostgreSQL的字符串类型有character.character varying和text的值.在使用character类型的时候, 它有自动填充空白的潜在影响,特别是在其它数据库(MySQL ...
- Lintcode: Product of Array Exclude Itself
Given an integers array A. Define B[i] = A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1], calculate B wi ...
- SQL 数据库 连接查询 变量、if else、while
一.连接查询:通过连接运算符可以实现多个表查询. 连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志. 常用的两个链接运算符: 1.join on(左右连接) 2.uni ...
- HTML中调用servlet的问题(?)
最近在学习servlet.刚开始时,按照案例一行一行的敲代码.不过,出问题了. hello1.html <!DOCTYPE html> <html> <head> ...
- zoj The 12th Zhejiang Provincial Collegiate Programming Contest Lunch Time
http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5499 The 12th Zhejiang Provincial ...
- Java基础(31):String的大小写转换、分离成数组、==与equals()的区别(String类)
继续来看 String 类常用的方法,如下代码所示: 运行结果: 那么,“==” 和 equals() 有什么区别呢? ==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象 eq ...
- 关于.Net Remoting 和 Web Servcie的比较
参照文献 http://www.cnblogs.com/shinehouse/articles/3001955.html http://www.cnblogs.com/paper/archive/20 ...
- openssh设置免密码登录远程服务器
主机 host | 远程机器 server 目标:从host登录到server,免密码输入 host机器: ssh-keygen -t rsa 在~/.ssh/中会生成两个文件 id_rsa.pub和 ...
- angularjs---$http.post发的数据,后台取不到
我用$http.post(url, data). 后台用play框架,不知道为什么总是取不到data数据.如果直接用$.post(url, data); 就可以! 后台Play的一个action: 打 ...
- c++ 容器(list学习总结)
list是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据).一个前驱指针和一个后驱指针.它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内 ...