Spring Aop(四)——基于Aspectj注解的Advice介绍

简介: 4 基于Aspectj注解的Advice介绍 之前介绍过,Advice一共有五种类型,分别是before、after return、after throwing、after(finally)和around。

4 基于Aspectj注解的Advice介绍

之前介绍过,Advice一共有五种类型,分别是before、after return、after throwing、after(finally)和around。在使用注解的时候,它们对应的注解分别是@Before、@AfterReturning、@AfterThrowing、@After和@Around。 这几个注解都是在org.aspectj.lang.annotation包中。

4.1 @Before

Before Advice将在目标方法执行前执行Advice逻辑,通过它我们可以在指定的切入点方法执行前加入特定的逻辑。如下是定义的一个Before Advice,通过其value属性(注解中只指定value属性时属性名是可以省略的)指定其需要拦截的切入点id或name为userService的bean的方法执行,然后拦截后我们只是简单的打印一条语句,在实际应用中这里应该加上我们特定的逻辑。

@Before("bean(userService)")
public void before() {
	System.out.println("-----before with pointcut expression: bean(userService)------");
}

注:

  • 1、@Before除了可以通过value属性指定需要拦截的切入点外,还可以指定一个argNames属性,这个是用于方便我们在Advice中访问切入点方法参数的,这个在后续会专门用一篇文章来讲如何在Advice中使用切入点方法参数。
  • 2、argNames这个属性不仅在@Before上有,在其它的Advice注解上也有。
  • 3、除非抛出异常,否则Before Advice是没法阻止程序继续往下执行的。

所有的Advice方法都可以接收一个JoinPoint参数,而且这个参数必须是Advice方法的第一个参数,通过这个参数我们可以获取到目标方法的一些信息,比如当前方法调用传递的参数信息、目标对象等。而如果是Around类型的Advice则必须接受一个ProceedingJoinPoint类型的参数,ProceedingJoinPoint是JoinPoint的子类。

@Before("bean(userService)")
public void before(JoinPoint joinPoint) {
	System.out.println("-----before with pointcut expression: bean(userService)------");
	joinPoint.getArgs();//获取当前目标方法调用传递的参数
	joinPoint.getSignature();//获取当前目标方法的签名,通过它可以获取到目标方法名
	joinPoint.getThis();//获取AOP生成的代理对象
	joinPoint.getTarget();//获取被代理对象,即目标对象
	System.out.println(joinPoint.getArgs());
	System.out.println(joinPoint.getSignature().getName());
	System.out.println(joinPoint.getThis().getClass());
	System.out.println(joinPoint.getTarget().getClass());
	System.out.println(joinPoint.toString());
}

4.2 @AfterReturning

AfterReturning Advice对应的是切入点方法正常执行完的拦截,即切入点方法执行时没有对外抛出异常,包括在目标方法被Around类型的Advice处理时没有抛出异常,如果目标方法在被Around类型的Advice处理时也抛出了异常,则同样会被认为目标方法是执行异常的,因为Around Advice是最先处理的,AfterReturning Advice会在Around Advice处理结束后才被触发的。如果我们希望在AfterReturning Advice中根据目标方法的返回结果做特定的业务逻辑,那么我们可以给AfterReturning Advice处理方法加一个参数,参数类型可以是你能确定的目标方法返回类型或用通用的Object,然后需要在@AfterReturning上通过returning属性指定目标方法的返回值需要赋值给AfterReturning Advice处理方法的哪个参数。如下示例中就在Advice处理方法上加入了一个通用类型的Object类型的returnValue参数,然后指定@AfterReturning的returning属性为“returnValue”。如果我们确定目标方法的返回结果一定是一个User类型的,那么我们也可以指定下面的方法参数类型是User类型。

@AfterReturning(value="bean(userService)", returning="returnValue")
public void afterReturning(Object returnValue) {
	System.out.println("-----after returning with pointcut expression: bean(userService)------");
	System.out.println("-----return value is: " + returnValue);
}

4.3 @AfterThrowing

AfterThrowing Advice对应的是切入点方法执行对外抛出异常的拦截。因为当一个切入点方法可以同时被Around Advice和AfterThrowing Advice拦截时,实际上AfterThrowing Advice拦截的是Around Advice处理后的结果,所以这种情况下最终AfterThrowing Advice是否能被触发,还要看Around Advice自身是否对外抛出异常,即算是目标方法对外抛出了异常,但是被Around Advice处理了又没有向外抛出异常的时候AfterThrowing Advice也不会被触发的。如果希望在AfterThrowing Advice处理方法中获取到被抛出的异常,可以给对应的Advice处理方法加一个Exception或其子类型(能确定抛出的异常类型)的方法参数,然后通过@AfterThrowing的throwing属性指定拦截到的异常对象对应的Advice处理方法的哪个参数。如下就指定了拦截到的异常对象将传递给Advice处理方法的ex参数。

@AfterThrowing(value="bean(userService)", throwing="ex")
public void afterThrowing(Exception ex) {
	System.out.println("-----after throwing with pointcut expression: bean(userService)------" + ex);
}

AfterThrowing是用于在切入点方法抛出异常时进行某些特殊的处理,但是它不会阻止方法调用者看到异常结果。

4.4 @After

After Advice就相当于try…catch…finally语句里面的finally的角色,即无论被拦截的切入点方法是成功执行完成还是对外抛出了异常,对应的Advice处理方法都将会执行。

@After("bean(userService)")
public void after() {
	System.out.println("-----after with pointcut expression: bean(userService)------");
}

4.5 @Around

Around Advice必须接收一个ProceedingJoinPoint类型的方法参数,然后在方法体中选择一个合适的时机来调用ProceedingJoinPoint的proceed方法以触发对目标方法的调用,然后Around Advice处理方法的返回值会被当做是目标方法调用的返回值。所以通过Around Advice我们可以在通过ProceedingJoinPoint调用目标方法的前后加上特定的逻辑,包括使用try…catch…finally等,所以Around Advice是功能最强大的一个Advice,前面的任何一种Advice在应用的时候都可以被Around Advice替换。

@Around("bean(userService)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
	System.out.println("-----around with pointcut expression: bean(userService)------");
	System.out.println("---------------------调用前---------------------");
	Object result = pjp.proceed();
	System.out.println("---------------------调用后---------------------");
	return result;
}

在上面的示例中我们就通过Around Advice拦截了id或name为userService的bean的所有方法调用,把真实的目标方法的返回结果返回去了。而实际上我们这里还可以修改目标方法的返回结果,比如常用的就是Spring的缓存会通过Around Advice在调用目标方法前先从缓存中获取结果,如果获取到了则直接返回。这也是Around Advice跟AfterReturning Advice一个比较大的差别,AfterReturning Advice是不能改变返回对象的引用的,但是它可以改变返回对象的个别属性。在使用Around Advice时也可以改变目标方法调用时传递的参数,这个时候要用到ProceedingJoinPoint 的带参数的proceed(Object[] args)方法了。如下示例中我们就在Around Advice中把调用目标方法的参数替换为15了。

@Around("bean(userService)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
	System.out.println("-----around with pointcut expression: bean(userService)------");
	System.out.println("---------------------调用前---------------------");
	Object[] params = new Object[]{15};
	Object result = pjp.proceed(params);//可以调整目标方法调用时传递的参数
	System.out.println("---------------------调用后---------------------");
	return result;
}

4.6 Advice执行顺序

官方的说法是在进入切入点前优先级越高的越先执行,而在从切入点出去时优先级越高的会越后执行。当一个切面类中定义了多个Advice需要作用于同一个切入点时它们的执行顺序是不确定的,理由是无法通过反射获取到这些Advice在编译好的字节码中的声明顺序,这种情况下官方建议将多种切面逻辑整合到一个Advice中处理,以免造成错误。当两个定义在不同的切面中的Advice需要作用在同一个切入点时,除非你在切面类上使用@Order注解指定了顺序,数字越小表示优先级越高,或者是使切面类实现Ordered接口。以下是官方原文地址。 http://docs.spring.io/spring/docs/4.1.0.RELEASE/spring-framework-reference/html/aop.html#aop-ataspectj-advice-ordering

(注:本文是基于Spring4.1.0所写,写于2017年1月19日星期四)

目录
相关文章
|
1月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
20天前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
46 5
|
25天前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
52 8
|
24天前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
24天前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
36 5
|
24天前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
35 4
|
2月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
48 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
1月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
37 1
|
1月前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
47 1
|
1月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
39 0
下一篇
DataWorks