时间:2021-05-19
前言
本文主要跟大家分享介绍了关于Spring AOP中@Aspect的高级用法,下面话不多说了,来随着小编一起看看详细的介绍吧。
1 切点复合运算
支持在切点定义中加入以下运算符进行复合运算:
运算符 说明 && 与运算。 ! 非运算。 || 或运算。
2 切点命名
一般情况下,切点是直接声明在需要增强方法处,这种切点的声明方式称为匿名切点,匿名切点只能在声明处被使用 。 如果希望在其它地方可以重用这个切点,我们可以通过 @Pointcut 注解及切面类方法来命名它。
public class NamePointcut { /** * 切点被命名为 method1,且该切点只能在本类中使用 */ @Pointcut("within(net.deniro.spring4.aspectj.*)") private void method1() { } /** * 切点被命名为 method2,且该切点可以在本类或子孙类中使用 */ @Pointcut("within(net.deniro.spring4.aspectj.*)") protected void method2() { } /** * 切点被命名为 method3,且该切点可以在任何类中使用 * 这里还使用了复合运算 */ @Pointcut("method1() && method2()") public void method3() { }}命名切点的结构如下:
切点可访问性修饰符与类可访问性修饰符的功能是相同的,它可以决定定义的切点可以在哪些类中可使用。
因为命名切点仅利用方法名及访问修饰符的信息,所以我们一般定义方法的返回类型为 void ,并且方法体为空 。
定义好切点后,就可以在切面类中引用啦:
@Aspectpublic class NamePointcutAspect { @After("NamePointcut.method2()") public void aspectMethod1() { } /** * 这里使用了复合运算 */ @After("NamePointcut.method2() && NamePointcut.method3()") public void aspectMethod2() { }}3 织入顺序
一个连接点可以同时匹配多个切点,而切点所对应的增强在连接点上织入顺序的规则是这样的:
1.如果在同一个切面类中声明的增强,则按照增强在切面类中定义的顺序进行织入;
2.如果增强位于不同的切面类中,并且这些切面类都实现了org.springframework.core.Ordered 接口,则由 Ordered 方法的顺序号决定(顺序号小的先织入);
3.如果增强位于不同的切面类中,但这些切面类没有实现org.springframework.core.Ordered 接口,织入的顺序是不确定的 。
假设有两个切面类 A 与 B,它们都实现了 Ordered 接口,A 的顺序号为 1,B 的顺序号为 2,切面类 A 与 B 都定义了 3 个增强,那么同时匹配这 6 个增强的织入顺序如下图所示:
4 获取连接点信息
4.1 JoinPoint
org.aspectj.lang.JoinPoint 接口表示目标类连接点对象,它定义这些主要方法。
方法 说明 Object[] getArgs() 获取连接点方法运行时的入参列表。 Signature getSignature() 获取连接点的方法签名对象。 Object getTarget() 获取连接点所在的目标对象。 Object getThis() 获取代理对象。
4.2 ProceedingJoinPoint
org.aspectj.lang.ProceedingJoinPoint 继承了 JoinPoint 接口,它新增了两个方法(它们用于执行连接点方法)。
方法 说明 Object proceed() throws Throwable 通过反射执行目标对象连接点处的方法。 Object proceed(Object[] var1) throws Throwable 使用新的入参(替换掉原来的入参),通过反射执行目标对象连接点处的方法。4.3 示例
Cook 接口:
public interface Cook { /** * 制作食品 */ void make(); /** * 制作 * * @param name 食品名称 */ void make(String name);}CookA 类:
public class CookA implements Cook { public void make() { System.out.println("制作食品"); } public void make(String name) { System.out.println("制作" + name); }}在切面类中访问连接点信息:
@Aspectpublic class JoinPointAspect { @Around("within(net.deniro.spring4.aspectj.CookA)") public void test(ProceedingJoinPoint pjp) throws Throwable { System.out.println("---------获取连接点对象【开始】---------"); System.out.println("参数:" + pjp.getArgs()[0]); System.out.println("签名对象:" + pjp.getTarget().getClass()); //执行目标对象方法 pjp.proceed(); System.out.println("---------获取连接点对象【结束】---------"); }}Spring bean 配置:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://.sun.proxy.$Proxy8 可以看出 ,CookD 类的注解 Log 对象也被代理咯O(∩_∩)O哈哈~8 绑定返回值
在后置增强中,可以通过 returning 来绑定连接点方法的返回值。
切面:
@Aspectpublic class ReturnValueAspect { @AfterReturning(value = "target(net.deniro.spring4.aspectj.CookA)", returning = "value") public void bind(boolean value) { System.out.println("绑定返回值【开始】"); System.out.println("value:" + value); System.out.println("绑定返回值【结束】"); }}注意:returning 的值必须与方法参数名相同。
CookA 新增 smell 方法:
public boolean smell(String name) { System.out.println(name + "香吗?"); return true;}单元测试:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");CookA cook = (CookA) context.getBean("cookA");cook.smell("烤鸭");输出结果:
烤鸭香吗?
绑定返回值【开始】
value:true
绑定返回值【结束】
9 绑定异常
可以使用 AfterThrowing 注解的 throwing 成员变量来绑定连接点抛出的异常。
切面类:
@Aspectpublic class ExceptionAspect { @AfterThrowing(value = "target(net.deniro.spring4.aspectj.CookA)",throwing = "e") public void bind(CookException e){ System.out.println("绑定异常【开始】"); System.out.println("e:" + e.getMessage()); System.out.println("绑定异常【结束】"); }}注意:throwing 的值必须与方法参数名相同。
单元测试:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");CookA cook = (CookA) context.getBean("cookA");cook.make("");输出结果:
绑定异常【开始】
e:煮啥呢???
绑定异常【结束】
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
面向切面编程(Aspect-orientedprogramming,AOP)是一种编程范式。做后端Javaweb的同学,特别是用过Spring的同学肯定对它非
Spring只支持XML方式而没有实现注解的方式(也叫AspectJ方式)的AOP,所以要使用@Aspect注解,只能引入AspectJ相关的jar包aopal
在阅读本文之前,大家可先参阅《简单理解Spring之IOC和AOP及代码示例》一文,了解下Spring中IOC和AOP的相关内容。下面进入正题。本篇文章介绍在S
在使用AOP的时候遇到了一些问题,特此记录一下首先写一个常用的AOP切片切片类AopLogpackagecom.mantis.aop.aspect;import
第一种:注解配置AOP注解配置AOP(使用AspectJ类库实现的),大致分为三步:1.使用注解@Aspect来定义一个切面,在切面中定义切入点(@Pointc