Spring AOP 切点指示器
Spring AOP借助AspectJ的切点表达式语言来定义Spring切面,下面是切点表达式中使用的指示器:
下面将通过一些测试案例来说明以上各个切点指示器的用法。另外 execution 不作额外说明,因为比较常见。
定义一个水果接口
定义一个甜水果类
定义一个产地接口
定义一个水果重量接口
定义一个苹果重量类
定义一个红苹果类
定义一个果农类
使用的测试类
SweetFruit 实现 Fruit 接口。 RedApple 继承 SweetFruit 并且实现 Origin 接口,并且关联 FruitWeight 接口。 AppleWeight 实现 FruitWeight 接口。
定义包含 within 指示器的切面
测试用例
within 指示器用来限定连接点必须在确定的类型或包中 ,在上面的切面中定义了 Fruit 、 SweetFruit 、 RedApple 这三个类型,根据输出发现只有 SweetFruit 、 RedApple 这两个切面进行了拦截。这说明了 within 指示器只拦截确定的类型,也就是跟它的接口无关,定义什么类型就拦截什么类型。
定义包含 this 指示器的切面
测试用例
this 指示器用来限定连接点属于给定类型的一个实例(代理对象) ,从上面的输出中可以看到, sweetFruit.print(); 被 this(...Fruit) 、 this(...SweetFruit) 拦截, redApple.print(); 和 redApple.printOrigin(); 被 this(...Fruit) 、 this(...SweetFruit) 、 this(...RedApple) 、 this(...Origin) 拦截。这说明了不管方法是来源于哪个接口或类( redApple.printOrigin(); 来源于 Origin 接口),只要代理对象的实例属于 this 中所定义的类型,那么这个方法就会被拦截。比如 sweetFruit 的代理对象既是 Fruit 的一个实例,也是 SweetFruit 的一个实例。 redApple 的代理对象分别属于 Fruit 、 SweetFruit 、 RedApple 、 Origin 这四个类型的一个实例。
注:我这边的测试环境显示AOP使用了CGLIB代理,也就是继承代理,所以代理对象同属以上接口或类,如果使用了JDK动态代理可能会产生不同的结果
定义包含 target 指示器的切面
测试用例
target 指示器用来限定连接点属于给定类型的一个实例(被代理对象) ,这个指示器的语义跟 this 指示器是很相似的,然后从上面的输出来看它们也是一样的(除了指示器不同)。但是它们有一个重要的区别, this 中的实例指的是代理对象,而 target 中的实例指的是被代理对象。
定义包含 args 指示器的切面 ,上面的切面表达式中额外定义了 within 指示器,这个主要是为了缩小 args 的使用范围。如果不加,Spring AOP会尝试去代理所有符合条件的对象,但是有些对象的访问会有限制,导致启动异常。这个也提醒我们使用AOP时必须要明确指定使用范围,否则会造成不可预料的错误。
测试用例 ,回顾一下之前定义的三个 printPrice 方法:
args 指示器用来限定连接点,也就是方法执行时它的参数属于给定类型的一个实例 ,从上面的输出来看,只有 public void printPrice(Integer price, String mesg) 这个方法被拦截,因为只有它符合条件。如果我们将定义改为 public void printPrice(String mesg,Integer price ) ,结果如下:
也就是说 args 指示器不但对参数类型有要求,而且还会对参数个数、定义顺序有要求。
定义包含 @target 指示器的切面
测试用例 ,然后回顾一下之前定义的 RedApple 这个类上所注解的 @Validated :
现在删除 RedApple 上的 @Validated 注解,将这个注解放到 SweetFruit 上,输出如下:
重复以上步骤,将 @Validated 注解放到 Fruit 接口上,输出如下:
@target 用来限定连接点属于一个执行对象(被代理对象)所属的拥有给定注解的类。 虽然 @target 和 target 名称相似,但是它们用法是完全不同的,前者针对注解,后置针对类型。另外从上面的输出可以看出 @target 限定在一个执行对象的所属类,与它的父类接口无关。
定义包含 @within 指示器的切面
测试用例 ,然后注意 redApple.print(11); 它是定义在 SweetFruit 类中
现在删除 RedApple 上的 @Validated 注解,将这个注解放到 SweetFruit 上,输出如下:
重复以上步骤,将 @Validated 注解放到 Fruit 接口上,输出如下:
@within 用来限定连接点属于拥有给定注解的类型中。 从上面的输出可以看出, @target 针对执行对象所属的类,而 @within 针对执行对象所属的类型。另外所执行的方法必须属于拥有给定注解的类型中,比如 redApple.print(); 被重写在 RedApple 类中, redApple.print(11); 被定义在 SweetFruit 类中,当这两个类拥有指定注解后方法执行时才会被拦截。最后需要注意的是 @within 和 within 只是名称接近,实际使用效果是不同的。
定义包含 @args 指示器的切面
测试用例 ,回顾一下在 RedApple 中定义的方法以及 FruitWeight 接口的定义:
现在删除 AppleWeight 上的 @JsonDeserialize 注解,将这个注解放到 FruitWeight 上,输出如下:
现在将 @JsonDeserialize 注解放到 AppleWeight 上,并且再定义一个继承了 AppleWeight 的子类:
测试用例
@args 用来限定连接点,方法执行时传递的参数的运行时类型拥有给定注解。 根据以上的输出以及 @args 的定义,这个给定的注解要么定义在方法参数的类型本身上,那么定义在的它的实现类上。比如 RedAppleWeight 它虽然继承了 AppleWeight (拥有指定注解),但是它本身没有指定注解,并且当 FruitWeight 也没有指定注解时,相关方法不会被拦截。
定义包含 @annotation 指示器的切面
测试用例 ,回顾一下 FruitFarmer 的定义:
现在删除 print() 上的 @JsonSerialize 注解,输出如下:
@annotation 用来限定连接点的方法拥有给定注解。 这个指示器比较容易理解,就是目标方法上拥有给定注解就可以了。
参考资源
僪苗鞣酸: 比较简单的方式可以用JoinPoint举个列子.package com.jf.my.Demo.AOP; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; ...
肃宁县18166523391: spring配置aop的方式有哪些 - ?
僪苗鞣酸: 在Spring中实现AOP根据版本不同,可以有大致四种配置方式.现简单列一下.在介绍Spring的AOP配置方式前,先要注意Spring中Advisor的概念.在Spring中Advisor是Advice和Pointcut的结合,但它还不是AOP概念上的Aspect.因为在...
肃宁县18166523391: AOP和IOC的概念以及在spring中是如何应用的 - ?
僪苗鞣酸: Spring中AOP的实现就是通过动态代理来实现的.动态代理的实现在上篇blog中已经涉及.Spring中目前最为实用的AOP应用,非用其实现的事务管理机制莫属.也正是这一点,使得Spring AOP大方异彩. 那么我们继续围绕上节的例子来探讨...
肃宁县18166523391: spring aop解决了什么问题 - ?
僪苗鞣酸: advisor 代表切面 由切点和通知组成.pointcut-ref 指定了切点,既在哪里切入逻辑,这里一般会设置匹配规则,就是对符合哪些条件的代码进行增强处理.advice-ref是要切入的增强(增强也有译为通知的)逻辑.
肃宁县18166523391: spring 里面的<aop:advisor >算是什么切法 - ?
僪苗鞣酸: 在aop中有几个概念:— 方面(aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象.事务管理是j2ee应用中一个很好的横切关注点例子.方面用spring的advisor或拦截器实现.— 连接点(joinpoint):程序执行过程中明...
肃宁县18166523391: 关于spring 配置事务问题 配置了切入点就出现了左边那个回转箭头符号,请问这个代表什么 - ?
僪苗鞣酸: 这个是正常的,配置没有错误.这个是spring的AOP标记.dao方法上出现标记这个证明你的dao方法满足你配置的事务管理规则(*.com.bpark.web.dao.*.*(..)).
肃宁县18166523391: Spring Aop中几个概念. - ?
僪苗鞣酸: 1.切面(aspect):要实现的交叉功能,是系统模块化的一个切面或领域.如日志记录. 2.连接点:应用程序执行过程中插入切面的地点,可以是方法调用,异常抛出,或者要修改的 字段. 3.通知:切面的实际实现,他通知系统新的行为.如在...
肃宁县18166523391: Spring的AOP有什么作用 - ?
僪苗鞣酸: AOP:面向切面,是一种编程思想,OOP的延续.将系统中非核心的业务提取出来,进行单独处理.比如事务、日志和安全等.这个简单来说就是可以在一段程序之前或者之后做一些事.
肃宁县18166523391: Spring 配置AOP切面注解报错,求教大虾 - ?
僪苗鞣酸: 有配置的,代码示例如下:这是业务测试类:package aop.annotation.service; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @Service("deptSerivceImpl") @Scope("prototype") public ...
肃宁县18166523391: spring aop 切入点 是必须的吗 - ?
僪苗鞣酸: 必须是可以,aop就是一个切面,只有找到切入点才能执行特定的功能.