基于@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 ...
随机推荐
- 事件监听addEventListener()和removeEventListener() ---------1
一直想写一个原生事件监听的记录,方便以后看,不愿意写主要是事件监听的单词太长,记起来好难记每次都要查,这次把知道的写完了,来这里查好了,以后要是理解的更透彻了,就再补全好了 首先,DOM0级事件和DO ...
- 转:python类型转换、数值操作
类型转换 1 函数 描述 2 int(x [,base ]) 将x转换为一个整数 3 ...
- 双端队列(单调队列)poj2823 区间最小值(RMQ也可以)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 41844 Accepted: 12384 ...
- [原创]java WEB学习笔记45:自定义HttpFilter类,理解多个Filter 代码的执行顺序,Filterdemo:禁用浏览器缓存的Filter,字符编码的Filter,检查用户是否登陆过的Filter
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- poj: 1207
好吧这题竟然还有先大后小的可能,能不这么恶心下吗.. #include <iostream> #include <stdio.h> #include <string.h& ...
- 。。。mkdir与mkdirs的区别。。。
一直想知道他俩的区别,也一直忘记了,知道今天才没有放过这个机会! mkdir的用法是正创建一层目录,比如说在C盘下创建aa文件夹,c:\aa,这个aa是不存在的,这个话,是可以用mkdir创建的,但是 ...
- CCSprite的使用方法大全
一.精灵创建及初始化 1.从图片文件创建: CCSprite *sprite = [CCSprite spriteWithFile:@"ImageFileName.png"]; 默 ...
- Session的工作机制详解和安全性问题(PHP实例讲解)
我们先简单的了解一些http的知识,从而理解该协议的无状态特性.然后,学习一些关于cookie的基本操作.最后,我会一步步阐述如何使用一些简单,高效的方法来提高你的php应用程序的安全性以及稳定行. ...
- angular 解析html
方法1:写filter <div ng-bind-html="showContent | html" class="detail-content"> ...
- 夺命雷公狗---DEDECMS----21dedecms按照地区取出电影内容
我们现在要做的就是: 这些电影都是要按照地区来取出才可以的,但是我们arclist标签里面有没有按照条件来查找的地方,我们只好换套路了,要不然条条大路都不通,,,, 我们先来构造一条语句: 他这个标签 ...