Spring中的AOP(五)——定义切入点和切入点指示符
定义切入点
在前文(点击查看)中使用到的AdviceTest类中同一个切点(即* com.abc.service.*.advice*(..)匹配的连接点)却重复定义了多次,这显然不符合软件设计的原则,为了解决这个问题,AspectJ和spring都提供了切入点的定义。所谓定义切入点,其实质就是为一个切入点表达式起一个名称,从而允许在多个增强处理中重用该名称。
Spring AOP只支持以Spring Bean的方法执行组作为连接点,所以可以把切入点看作所有能和切入表达式匹配的Bean方法。切入点定义包含两个部分:
一个切入点表达式:用于指定切入点和哪些方法进行匹配
一个包含名字和任意参数的方法签名:将作为切入点的名称
在@AspectJ风格的AOP中,切入点签名采用一个普通的方法定义(方法体通常为空)来提供(方法名即为切点名),且该方法的返回值必须为void,切入点表达式需使用@Pointcut注解来标注。下面的代码片段定义了一个切入点,这个切入点将匹配任何名为transfer的方法的执行:
| 
 1 
2 
3 
4 
 | 
//使用@Pointcut注解时指定切入点表达式@Pointcut("execution(* transfer(..))")//使用一个返回值为void,方法体为空的方法来命名切入点,方法名即为切点名private void myPointcut(){} | 
切入点表达式,也就是组成@Pointcut注解的值,是规范的AspectJ 5切入点表达式。如果想要了解更多的关于AspectJ切入点语言,请参见AspectJ编程指南。
一旦采用上面的代码片段定义了名为myPointcut的切入点之后,程序就可以多次重复使用该切点了,甚至可以在其他切面类、其他包的切面类里使用该切点,至于是否可以在其他切面类、其他包下使用这个切点,那就要看该方法前的访问控制修饰符了——本例中myPointcut使用private修饰,则意味着仅能在当前切面类中使用这个切点。
如果需要使用本切面类中的切点,则可在使用@Pointcut注解时,指定value属性值为已有的切入点,如下:
| 
 1 
2 
3 
4 
 | 
@AfterReturning(pointcut="myPointcut()", returning="returnValue")public void log(String message, Object returnValue) {    //do something...} | 
从指定pointcut来看,其语法非常类似于Java中调用方法——只是该方法代表一个切点,其实质是为该增强处理方法定义一个切入点表达式。如果需要使用其他类中定义的切点,则定义这些切点的方法的修饰符不能为private。现在假设在另一个类PointcutDefinition中定义了一个名为myPointcutTest的切点:
| 
 1 
2 
3 
4 
5 
 | 
public class PointcutDefinition {    @Pointcut("execution(* something(..))")    //访问控制符为public,这个切点可以在其他任何地方引用    public void myPointcutTest(){}} | 
则在引用的时候需要带上类名,例如:
| 
 1 
2 
3 
4 
5 
6 
 | 
@AfterReturning(    pointcut="PointcutDefinition.myPointcutTest() && args(message)",     returning="returnValue")public void log(String message, Object returnValue) {    //do something...} | 
切入点指示符
前面定义切点表达式时使用了大量的execution表达式,其中execution就是一个切入点指示符。Spring AOP仅支持部分AspectJ的切入点指示符,但Spring AOP还额外支持一个bean切入点指示符。不仅如此,因为Spring AOP只支持使用方法调用作为连接点,所以Spring AOP的切入点指示符仅匹配方法执行的连接点。
完整的AspectJ切入点语言支持大量切入点指示符,但是Spring并不支持它们。它们是:call,get,preinitialization,staticinitialization,initialization,handler,adviceexecution,withincode,cflow,cflowbelow,if,@this和@withincode。一旦在Spring AOP中使用这些切点指示符,就会抛出IllegalArgumentException。
Spring AOP支持的切入点指示符有如下几个:
execution:用于匹配执行方法的连接点,这是Spring AOP中国最主要的切入点指示符。该切入点的用法也相对复杂,execution表达式的格式如下:
execution(modifier-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
上面的格式中,execution是不变的,用于作为execution表达式的开头,整个表达式中几个参数的详细解释如下:
modifier-pattern:指定方法的修饰符,支持通配符,该部分可以省略
ret-type-pattern:指定返回值类型,支持通配符,可以使用“*”来通配所有的返回值类型
declaring-type-pattern:指定方法所属的类,支持通配符,该部分可以省略
name-pattern:指定匹配的方法名,支持通配符,可以使用“*”来通配所有的方法名
param-pattern:指定方法的形参列表,支持两个通配符,“*”和“..”,其中“*”代表一个任意类型的参数,而“..”代表0个或多个任意类型的参数。
throw-pattern:指定方法声明抛出的异常,支持通配符,该部分可以省略
如下是几个execution表达式:
execution(public * * (..))//匹配所有public方法
execution(* set*(..))//匹配以set开始的方法
execution(* com.abc.service.AdviceManager.* (..))//匹配AdviceManager中任意方法
execution(* com.abc.service.*.* (..))//匹配com.abc.servcie包中任意类的任意方法
within:限定匹配特定类型的连接点,当使用Spring AOP的时候,只能匹配方法执行的连接点。下面是几个例子:
within(com.abc.service.*)//匹配com.abc.service包中的任意连接点
within(com.abc.service..*)//匹配com.abc.service包或子包中任意的连接点
this:用于指定AOP代理必须是指定类型的实例,用于匹配该对象的所有连接点。当使用Spring AOP的时候,只能匹配方法执行的连接点。下面是个例子:
this(com.abc.service.AdviceManager)//匹配实现了AdviceManager接口的代理对象的所有连接点,在Spring中只是方法执行的连接点
target:用于限定目标对象必须是指定类型的实例,用于匹配该对象的所有连接点。当使用Spring AOP的时候,只能匹配方法执行的连接点。下面是个例子:
target(com.abc.servcie.AdviceManager)//匹配实现了AdviceManager接口的目标对象的所有连接点,在Spring中只是方法执行的连接点
args:用于对连接点的参数类型进行限制,要求参数的类型时指定类型的实例。同样,当使用Spring AOP的时候,只能匹配方法执行的连接点。下面是个例子:
args(java.io.Serializable)//匹配只接受一个参数,且参数类型是Serializable的所有连接点,在Spring中只是方法执行的连接点
注意,这个例子与使用execution(* *(java.io.Serializable))定义的切点不同,args版本只匹配运行时动态传入参数值是Serializable类型的情形,而execution版本则匹配方法签名只包含一个Serializable类型的形参的方法。
另外,Spring AOP还提供了一个名为bean的切入点提示符,它是Spring AOP额外支持的,并不是AspectJ所支持的切入点指示符。这个指示符对Spring框架来说非常有用:它将指定为Spring中的哪个Bean织入增强处理。当然,Spring AOP中只能使用方法执行作为连接点。
bean:用于指定只匹配该Bean实例内的连接点,实际上只能使用方法执行作为连接点。定义bean表达式时需要传入Bean的id或name,支持使用"*"通配符。下面是几个例子:
bean(adviceManager)//匹配adviceManager实例内方法执行的连接点
bean(*Manager)//匹配以Manager结尾的实例内方法执行的连接点
使用组合切点表达式
Spring支持使用如下三个逻辑运算符来组合切入点表达式:
&&:要求连接点同时匹配两个切点表达式
||:要求连接点匹配至少一个切入点表达式
!:要求连接点不匹配指定的切入点表达式
其实在之前介绍args的时候,已经用到了“&&”运算符:
| 
 1 
 | 
pointcut("execution(* com.abc.service.*.*(..) && args(name))") | 
上面的pointcut由两个表达式组成,而且使用&&来组合这两个表达式,因此连接点需要同时满足这两个表达式才能被织入增强处理。
http://blog.csdn.net/caomiao2006/article/details/51287204
Spring中的AOP(五)——定义切入点和切入点指示符的更多相关文章
- (五)Spring 中的 aop
		
目录 文章目录 AOP概念 AOP原理 AOP术语 **`Spring`** 中的 **`aop`** 的操作 使用 `AspectJ` 实现 `aop` 的两种方式 AOP概念 浅理解 aop :面 ...
 - Spring中的AOP 专题
		
Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...
 - Spring学习笔记(四)—— Spring中的AOP
		
一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...
 - Spring 中基于 AOP 的 @AspectJ
		
Spring 中基于 AOP 的 @AspectJ @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格. 通过在你的基于架构的 XML ...
 - Spring 中基于 AOP 的 XML架构
		
Spring 中基于 AOP 的 XML架构 为了使用 aop 命名空间标签,你需要导入 spring-aop j架构,如下所述: <?xml version="1.0" e ...
 - Spring中的AOP
		
什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...
 - spring中的AOP 以及各种通知 配置
		
理解了前面动态代理对象的原理之后,其实还是有很多不足之处,因为如果在项目中有20多个类,每个类有100多个方法都需要判断是不是要开事务,那么方法调用那里会相当麻烦. spring中的AOP很好地解决了 ...
 - 2018.12.24 Spring中的aop演示(也就是运用aop技术实现代理模式)
		
Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 1.spring中的aop演示 aop:面向方面编程.不 ...
 - JavaWeb_(Spring框架)认识Spring中的aop
		
1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...
 - spring中bean的五种作用域?Spring中的bean是线程安全的吗?
		
spring中bean的五种作用域 当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...
 
随机推荐
- ConcurrentHashMap 分析
			
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/76795383 构造函数 JDK 1.5 引入了 ConcurrentHashMap . ...
 - 从JDK源码角度看Short
			
概况 Java的Short类主要的作用就是对基本类型short进行封装,提供了一些处理short类型的方法,比如short到String类型的转换方法或String类型到short类型的转换方法,当然 ...
 - webpack 提升90%的构建速度 HardSourceWebpackPlugin
			
HardSourceWebpackPlugin 插件 不能提升第一次构建的速度,但对于第二次构建能提升99%的构建速度 第一次构建: 第二次: 提升了..,算不出来,反正就是很多啦~~~ npm in ...
 - spring-security-4 (3)spring security过滤器的创建与注册原理
			
spring security是通过一个过滤器链来保护你的web应用安全.在spring security中,该过滤链的名称为springSecurityFilterChain,类型为FilterCh ...
 - Promise的并行和串行
			
Promise 并行 这个功能Promise自身已经提供,不是本文的重点.主要是依赖Promise.all和Promise.race. Promise.all是所有的Promise执行完毕后(reje ...
 - POI2012题解
			
POI2012题解 这次的完整的\(17\)道题哟. [BZOJ2788][Poi2012]Festival 很显然可以差分约束建图.这里问的是变量最多有多少种不同的取值. 我们知道,在同一个强连通分 ...
 - kudu yum 安装
			
yum 源 http://archive.cloudera.com/kudu/redhat/7/x86_64/kudu/cloudera-kudu.repo [cloudera-kudu] # Pac ...
 - gqlgen golang graphql server 基本试用
			
gqlgen golang 的graphql server 具体代码参考https://github.com/rongfengliang/gqlgen-demo 特点 模型优先 类型安全 代码生成 安 ...
 - oracle 查版本号
			
oracle是强大的数据库,我们怎样看它的版本呢? 工具/原料 oracle 数据库, sqlplus 方法/步骤 首先进入sqlplus,cmd---plsql,登陆我们的用户,如:user/pas ...
 - 关于 ThinkPHP5 使用 getBy 字段名方式获取数据
			
关于 ThinkPHP5 使用 getBy 字段名方式获取数据 有小伙半说怎么全文搜索都没有搜索到 getByName 之类的函数. 其实是在这里.