AspectJ中的五种增强注解及其详解

6 篇文章 0 订阅

Aspectj注解实现AOP

1、添加jar类库

 

2.在spring配置文件中添加如下代码

	<context:component-scan base-package="com.jd"></context:component-scan>
	<bean class="com.jd.calculator.CalculatorService"></bean>
	
	<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

第一行是扫描自定义的包,这次所有与测试相关的类都在com.jd中

第二行是创建一个自定义的类的bean放在IOC容器中

第三行解释:如果创建目标对象的目标类中的方法与AspectJ切面中切入点表达式匹配,则自动为该目标对象生成动态代理对象,该代理对象默认使用JDK动态代理,即proxy-target-class="false" ,当为true时为CGLib代理。

3.此次测试代码

①.CalculatorAspect类(设置增强方法)

@Aspect
@Component
public class CalculatorAspect {

	@Pointcut("execution(int com.jd.calculator.CalculatorService.*(int,int))")
	public void pointcut() {
		
	}
	@Before("pointcut()")
	public void before(JoinPoint joinpoint) {
		Object object = joinpoint.getTarget();//获取目标对象
		Object [] args = joinpoint.getArgs();
		String name = joinpoint.getSignature().getName();
		System.out.println(object.getClass().getName()+":The "+name+" method begins.");
		System.out.println(object.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");		
	}
	@AfterReturning(value="pointcut()",returning="result")
	public void afterReturning(JoinPoint joinPoint,Object result) {
		Object object = joinPoint.getTarget();
		String name = joinPoint.getSignature().getName();
		System.out.println(object.getClass().getName()+":Result of the "+name+" method:"+result);
	}
	@After("pointcut()")
	public void after(JoinPoint joinPoint) {
		Object object = joinPoint.getTarget();
		String name = joinPoint.getSignature().getName();
		System.out.println(object.getClass().getName()+":The "+name+" method ends.");
	}
	
	@AfterThrowing(value="pointcut()",throwing="excption")
	public void afterThrowing(JoinPoint joinPoint,Exception excption) {
		Object object = joinPoint.getTarget();
		String name = joinPoint.getSignature().getName();
		System.out.println(object.getClass().getName()+":Exception of the method "+name+": "+excption);
	}
	
}

②.CalculatorService类

@Component
public class CalculatorService implements ICalculatorService{

	@Override
	public int mul(int a, int b) {
		int result = a*b;
		return result;
	}

	@Override
	public int div(int a, int b) {
		int result = a/b;
		return result;
	}

}

③.ICalculatorService接口

public interface ICalculatorService {

	int mul(int a, int b);

	int div(int a, int b);

}

④.Test类

public class Test {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("app.xml");
		ICalculatorService calculatorService = context.getBean(ICalculatorService.class);
		int result = calculatorService.div(1, 1);
		System.out.println(result);
		context.close();
	}
}

4.分析增强的执行过程

执行Test类中的main方法发现执行结果如下

我们故意设置一个错误(在service类中)

@Override
public int div(int a, int b){
		int result = a/b;
		if(a==0) {
			throw new RuntimeException("1111111");
		}
		return result;
	}

执行结果如下

 

 

我们将println的输出与增强方法一一对应,我们会发现增强方法的执行过程是加有@Before注解的方法 -->执行增强的目标方法-->@After注解所修饰的方法-->@AfterReturning注解所修饰的方法-->@AfterThrowing注解所修饰的方法

实际上这些方法是这样执行的

@Around

AspectJ一共支持5种类型的增强注解,除了@Before,@After,@AfterReturning和@AfterThrowing以外,还有一种增强注解——@Around,在@Around修饰的方法中可以实现@Before,@After,@AfterReturning和@AfterThrowing增强效果,可以实现动态代理全过程,代码如下:

@Aspect
@Component
public class CalculatorAspect {

	@Pointcut("execution(int com.jd.calculator.CalculatorService.*(int,int))")
	public void pointcut() {
		
	}

	@Around("pointcut()")
	public Object around(ProceedingJoinPoint joinPoint) {
		Object result=null;
		Object object = joinPoint.getTarget();//获取目标对象
		Object [] args = joinPoint.getArgs();
		String name = joinPoint.getSignature().getName();
		try {
			try {
				//前置增强
				System.out.println(object.getClass().getName()+":The "+name+" method begins.");
				System.out.println(object.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
				result = joinPoint.proceed();
			} finally{
				System.out.println(object.getClass().getName()+":The "+name+" method ends.");
				//后置增强
			}
			//返回增强
			System.out.println(object.getClass().getName()+":Result of the "+name+" method:"+result);
		} catch (Throwable e) {
			System.out.println(object.getClass().getName()+":Exception of the method "+name+": "+e);
		}
		return result;
	}
	
}

 

结果如下

与上面执行结果相同,因此可得出一个结论@Around注解的方法可以代替其他四种增强方法

注意:如果 @AfterThrowing所注解的方法中 异常的类型若与方法中抛出的异常类型不匹配会怎样呢?

相应的方法修改如下

	@Override
	public int div(int a, int b){
		int result = a/b;
		if(a==0) {
			throw new ArithmeticException("!!!!!!!!!!!!");
		}
		return result;
	}
@AfterThrowing(value="pointcut()",throwing="excption")
	public void afterThrowing(JoinPoint joinPoint,NullPointerException excption) {
		Object object = joinPoint.getTarget();
		String name = joinPoint.getSignature().getName();
		System.out.println(object.getClass().getName()+":Exception of the method "+name+": "+excption);
	}

运行结果如下

 

也就是说@AfterThrowing注解的方法并没有起作用

使用最先提到的四种注解与@Around注解的区别
1.@Before、@After、@AfterRunning和@AfterThrowing修饰的方法可以通过声明JoinPoint 类型参数变量获取目标方法的信息;@Around修饰的方法必须声明ProceedingJoinPoint类型的参数获取目标方法的信息
2.@Before、@After、@AfterRunning和@AfterThrowing修饰的方法没有返回值;而@Around修饰的方法必须有返回值,返回值为目标方法的返回值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值