AspectJ中的5种类型的增强注解

一、AspectJ中的5种类型的增强注解

Test类中的代码:

package com.jd.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.calculator.ICalculatorService;

public class Test {

	public static void main(String[] args) {
		//创建IOC容器并创建对象
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
		ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
		int result = calculatorService.mul(1, 1);
		System.out.println("-->"+result);
	}
}

1.@Before(前置增强)

在目标方法执行之前执行

@Before("execution(int mul(int, int))")
public void before(JoinPoint jp) {
	Object target = jp.getTarget();
	Object [] args = jp.getArgs();
	String name = jp.getSignature().getName();
	System.out.println(target.getClass().getName()+":The "+name+" method begins.");
	System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
}

运行结果:

com.jd.calculator.CalculatorService:The mul method begins.
com.jd.calculator.CalculatorService:Parameters of the mul method: [1,1]
-->1

2.@After(后置增强)

在目标方法执行后执行,无论目标方法运行期间是否出现异常。注意:后置增强无法获取目标方法执行结果,可以在返回增强中获取

@After("execution(int mul(int, int))")
public void after(JoinPoint jp) {
	Object target = jp.getTarget();
	String name = jp.getSignature().getName();
	System.out.println(target.getClass().getName()+":The "+name+" method ends.");
}

运行结果:

com.jd.calculator.CalculatorService:The mul method ends.
-->1

3.@AfterReturning(返回增强)

在目标方法正常结束后执行,可以获取目标方法的执行结果

@AfterReturning(value="execution(int mul(int, int))",returning="result")
public void afterReturning(JoinPoint jp,Object result) {
	Object target = jp.getTarget();
	String name = jp.getSignature().getName();
	System.out.println(target.getClass().getName()+":Result of the "+name+" method:"+result);
}

运行结果:

com.jd.calculator.CalculatorService:Result of the mul method:1
-->1

4.@AfterThrowing(异常增强)

目标方法抛出异常之后执行,可以访问到异常对象,且可以指定在出现哪种异常时才执行增强代码

@AfterThrowing(value="execution(int mul(int, int))",throwing="ex")
public void afterThrowing(JoinPoint jp,ArithmeticException ex) {
	Object target = jp.getTarget();
	String name = jp.getSignature().getName();
	System.out.println(target.getClass().getName()+":The "+name+" method had an exception."+ex.getMessage());
}

让CalculatorService 类中调用的该方法报异常

package com.jd.calculator;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService {

	@Override
	public int mul(int a, int b) {
		int result = a*b;
		if(result==1) {
			throw new RuntimeException("两数之积不能为1");
		}
		return result;
	}

运行结果:
在这里插入图片描述

5.@Around(环绕增强)

目标方法执行前后都可以织入增强处理

@Around("execution(int mul(..))")
	public Object around(ProceedingJoinPoint jp) {
		Object target = jp.getTarget(); 
		Object [] args = jp.getArgs();
		String name = jp.getClass().getName();
		Object result = null;
		try {
			try {
				//前置增强
				System.out.println(target.getClass().getName()+":The "+name+" method begins.");
				System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
				result = jp.proceed();
			}finally{
				//后置增强
				System.out.println(target.getClass().getName()+":The "+name+" method ends.");
			}
			//返回增强
			System.out.println(target.getClass().getName()+":Result of the "+name+" method:"+result);
		} catch (Throwable e) {
			//异常增强
			System.out.println(target.getClass().getName()+":The "+name+" method had an exception."+e.getMessage());
			e.printStackTrace();
		}
		return result;

出异常时的结果:

com.sun.proxy.$Proxy8
com.jd.calculator.CalculatorService:The org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method begins.
com.jd.calculator.CalculatorService:Parameters of the org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method: [1,1]
com.jd.calculator.CalculatorService:The org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method ends.
com.jd.calculator.CalculatorService:The org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method had an exception.两数之积不能为1
java.lang.RuntimeException: 两数之积不能为1

不出异常时的结果:

com.sun.proxy.$Proxy8
com.jd.calculator.CalculatorService:The org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method begins.
com.jd.calculator.CalculatorService:Parameters of the org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method: [1,1]
com.jd.calculator.CalculatorService:The org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method ends.
com.jd.calculator.CalculatorService:Result of the org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint method:1
-->1

二、AspectJ中的注解的执行特定

1.环绕增强的特点

@Around中可以实现@Before、@AfterRunning、@AfterThrowing、@After中任意一种或多种

2.执行顺序

try {
	try {
		doBefore();// @Before注解所修饰的方法
		method.invoke();// 执行目标对象内的方法
	} finally {
		doAfter();// @After注解所修饰的方法
	}
	doAfterReturning();// @AfterReturning注解所修饰的方法
} catch (Exception e) {
	doAfterThrowing();// @AfterThrowing注解所修饰的方法
}

由上图或@Around(环绕增强)的代码分析可知:先执行前置增强——>再调用目标方法
——>再执行后置增强——>最后执行返回增强(不报异常时)或执行异常增强(报异常时)

3.异常增强执行的特点

①@Before、@AfterRunning、@AfterThrowing、@After四种增强同时存在时

	//前置增强
	@Before("execution(int mul(int, int))")
	public void before(JoinPoint jp) {
		Object target = jp.getTarget();
		Object [] args = jp.getArgs();
		String name = jp.getSignature().getName();
		System.out.println(target.getClass().getName()+":The "+name+" method begins.");
		System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
	}
	//返回增强
	@AfterReturning(value="execution(int mul(int, int))",returning="result")
	public void afterReturning(JoinPoint jp,Object result) {
		Object target = jp.getTarget();
		String name = jp.getSignature().getName();
		System.out.println(target.getClass().getName()+":Result of the "+name+" method:"+result);
	}
	//后置增强
	@After("execution(int mul(int, int))")
	public void after(JoinPoint jp) {
		Object target = jp.getTarget();
		String name = jp.getSignature().getName();
		System.out.println(target.getClass().getName()+":The "+name+" method ends.");
	}
	//异常增强(又称异常通知)
	@AfterThrowing(value="execution(int mul(int, int))",throwing="ex")
	public void afterThrowing(JoinPoint jp,Exception ex) {
		Object target = jp.getTarget();
		String name = jp.getSignature().getName();
		System.out.println(target.getClass().getName()+":The "+name+" method had an exception."+ex.getMessage());
	}

执行结果如下:
在这里插入图片描述

②e变量数据类型不同时

在这里插入图片描述
CalculatorService类中:

@Override
public int mul(int a, int b) {
	int result = a*b;
	if(result==1) {
		throw new RuntimeException("两数之积不能为1");
	}
	return result;
}
(1)e变量数据类型为RuntimeException时
@AfterThrowing(value="execution(int mul(int, int))",throwing="ex")
public void afterThrowing(JoinPoint jp,Exception ex) {
	Object target = jp.getTarget();
	String name = jp.getSignature().getName();
	System.out.println(target.getClass().getName()+":The "+name+" method had an exception."+ex.getMessage());
}

爆发异常,正常执行异常增强
在这里插入图片描述

(2)e变量数据类型为NullPointException或ArithmeticException时
@AfterThrowing(value="execution(int mul(int, int))",throwing="ex")
public void afterThrowing(JoinPoint jp,NullPointerException ex) {
	Object target = jp.getTarget();
	String name = jp.getSignature().getName();
	System.out.println(target.getClass().getName()+":The "+name+" method had an exception."+ex.getMessage());
}

爆发异常,不执行异常增强在这里插入图片描述

3.区别

①@Before、@After、@AfterRunning和@AfterThrowing修饰的方法可以通过声明JoinPoint 类型参数变量获取目标方法的信息;@Around修饰的方法必须声明ProceedingJoinPoint类型的参数获取目标方法的信息
②@Before、@After、@AfterRunning和@AfterThrowing修饰的方法没有返回值;而@Around修饰的方法必须有返回值,返回值为目标方法的返回值

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值