基于@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 ...
随机推荐
- MySQL编码问题
client 下的default_character_set=utf8; 它是需要的,可是它的作用是干吗的? 它的作用等同执行以下3个命令 SET character_set_client = utf ...
- 使用Eclipse构建Maven项目 (转)
Maven这个个项目管理和构建自动化工具,越来越多的开发人员使用它来管理项目中的jar包.本文仅对Eclipse中如何安装.配置和使用Maven进行了介绍.完全step by step. 如果觉得本文 ...
- Oracle数据类型总结
一 字符串类型 1.1:CHAR类型 CHAR(size [BYTE | CHAR]) CHAR类型,定长字符串,会用空格填充来达到其最大长度.非NULL的CHAR(12)总是包含12字节信息.CHA ...
- LDA-math-认识Beta/Dirichlet分布
http://cos.name/2013/01/lda-math-beta-dirichlet/#more-6953 2. 认识Beta/Dirichlet分布2.1 魔鬼的游戏—认识Beta 分布 ...
- LDA-math-神奇的Gamma函数
http://cos.name/2013/01/lda-math-gamma-function/ 1. 神奇的Gamma函数1.1 Gamma 函数诞生记学高等数学的时候,我们都学习过如下一个长相有点 ...
- PAT乙级 1011. A+B和C (15)
1011. A+B和C (15) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 HOU, Qiming 给定区间[-231, 231 ...
- 【sublime】插件安装:包管理器——Package Control
首先,按CTRL+`,打开控制台 粘贴下面的代码,之后回车 如果是sublime3 import urllib.request,os,hashlib; h = '7183a2d3e96f11eea ...
- 最长上升子序列O(nlogn)算法详解
最长上升子序列 时间限制: 10 Sec 内存限制:128 MB 题目描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.我们想知道此时最长上升子 ...
- 161014、Comet4J介绍及使用(即时推送)
简介 Comet4J是一个微型的即时推送框架(类似于goeasy),它分为服务端与客户端两部分,你只要将服务器端(JAR文件,目前仅支持Tomcat6.7)放入WEB-INF\lib,客户端(Java ...
- Javascript Regexp match and replace
# add a new article reference to database function addnewpub() { var year = $("input#year" ...