基于@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 ...
随机推荐
- 解决xcode6_beta没有代码提示的方法
在beta版本的xcode6中我们会发现代码提示不怎么好使,但是看一些老外的视频,他们的代码提示却又是赶赶的.这是为什么呢?其实解决办法也很简单.就是在项目中不出现中文字符就好了.有的同学说,我没用中 ...
- acm算法模板(1)
1. 几何 4 1.1 注意 4 1.2 几何公式 4 1.3 多边形 6 1.4 多边形切割 9 1.5 浮点函数 10 1.6 面积 15 1.7 球面 16 1.8 三角形 17 1.9 三维几 ...
- [原创]java WEB学习笔记53:Struts2学习之路---前奏:使用 Filter 作为控制器的 MVC
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- android ANR问题
一.什么是ANR ANR:Application Not Responding: 具体请参考:http://blog.csdn.net/dadoneo/article/details/8270107
- MyEclipse 下 Tomcat启动变慢如何解决
MyEclipse 下 Tomcat启动变慢如何解决 项目使用debug启动有时候会突然变得非常慢.不但启动慢,启动之后连打开项目页面也很慢,是日常的4,5倍.可以有下面的几种解决方法: 1. ...
- radio应用
1.获取选中值,三种方法都可以: $('input:radio:checked').val(): $("input[type='radio']:checked").val(); $ ...
- Oracle重置序列(不删除重建方式)
Oracle中一般将自增sequence重置为初始1时,都是删除再重建,这种方式有很多弊端,依赖它的函数和存储过程将失效,需要重新编译. 不过还有种巧妙的方式,不用删除,利用步长参数,先查出seque ...
- 夺命雷公狗---Thinkphp----3之后台搭建
我们这里来搭建我们网站所需要用到的后台: 我们直接打开WEB目录,然后直接赋值Home文件粘贴并改名为Admin,效果如下所示: 然后修改他的控制器: 代码修改成如下所示: <?php name ...
- HTML输入框点击内容消失
在input标签中这样写 type='text' onfocus='if(this.value=='请输入内容以搜索') this.value=''' onblur='if(this.value==' ...
- opencv载入,显示及保存图像
1.声明一个表示图像的变量,在OpenCV2中,这个变量是cv::Mat类型,该类是用于保存图像以及其他矩阵数据的数据结构.默认情况下它们的尺寸为0. cv::Mat image; // ...