文章目录
五种代理增强注解方法
//前置增强(又称前置通知):在目标方法执行之前执行
@Before("execution(public int com.jd.calculator.CalculatorService.*(..))")
public void before(JoinPoint joinPoint) {
Object target=joinPoint.getTarget();
String methodName = joinPoint.getSignature().getName();
Object[] params = joinPoint.getArgs();
System.out.println(target.getClass().getName()+":The "+methodName+" method begins.");
System.out.println(target.getClass().getName()+":Parameters of the "+methodName+" method: ["+params[0]+","+params[1]+"]");
}
//后置增强(又称后置通知):在目标方法执行后执行,无论目标方法运行期间是否出现异常。注意:后置增强无法获取目标方法执行结果,可以在返回增强中获取
@After("execution(public int com.jd.calculator.CalculatorService.*(..))")
public void after(JoinPoint joinPoint) {
Object target=joinPoint.getTarget();
String methodName = joinPoint.getSignature().getName();
System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
}
//返回增强(又称返回通知):在目标方法正常结束后执行,可以获取目标方法的执行结果
@AfterReturning(value="execution(public int com.jd.calculator.CalculatorService.*(..))",returning="result")
public void afterReturning(JoinPoint joinPoint,Object result) {
Object target=joinPoint.getTarget();
String methodName = joinPoint.getSignature().getName();
System.out.println(target.getClass().getName()+":Result of the "+methodName+" method:"+result);
}
//异常增强(又称异常通知):目标方法抛出异常之后执行,可以访问到异常对象,且可以指定在出现哪种异常时才执行增强代码
@AfterThrowing(value="execution(public int com.jd.calculator.CalculatorService.*(..))", throwing="e")
public void afterThrowing(JoinPoint joinPoint,Exception e) {//e变量数据类型为Exception,ArithmeticException异常时Exception的子类,所以目标方法出现异常时afterThrowing方法可以执行;如果e的数据类型为NullPointerException,则目标方法出现异常后afterThrowing方法不会执行
Object target=joinPoint.getTarget();
String methodName = joinPoint.getSignature().getName();
System.out.println(target.getClass().getName()+":Exception of the method "+methodName+": "+e);
}
//环绕增强:目标方法执行前后都可以织入增强处理
@Around("execution(public int com.jd.calculator.CalculatorService.*(..))")
public Object around(ProceedingJoinPoint joinPoint) {
Object result = null;
Object target=joinPoint.getTarget();//目标对象
String methodName = joinPoint.getSignature().getName();
Object[] params = joinPoint.getArgs();
try {
try {
//前置增强
System.out.println(target.getClass().getName()+":The "+methodName+" method begins.");
System.out.println(target.getClass().getName()+":Parameters of the "+methodName+" method: ["+params[0]+","+params[1]+"]");
//执行目标对象内的方法
result = joinPoint.proceed();
}finally {
//后置增强
System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
}
//返回增强
System.out.println(target.getClass().getName()+":Result of the "+methodName+" method:"+result);
} catch (Throwable e) {
//异常增强
System.out.println(target.getClass().getName()+":Exception of the method "+methodName+": "+e);
}
return result;
}
}
区别
很明显环绕注解方法相对于其他四个注解方法的第一个参数类型不同,实际上,由public abstract interface org.aspectj.lang.ProceedingJoinPoint extends org.aspectj.lang.JoinPoint
很明显看出前者ProceedingJoinPoint是后者JoinPoint的子类,并且可以使用proceed()方法获取目标方法的返回值。
同时环绕方法实质上将前面四种方法前置、后置、返回、异常增强包含在内,顺序为
try {
try {
doBefore();// @Before注解所修饰的方法
method.invoke();// 执行目标对象内的方法
} finally {
doAfter();// @After注解所修饰的方法
}
doAfterReturning();// @AfterReturning注解所修饰的方法
} catch (Exception e) {
doAfterThrowing();// @AfterThrowing注解所修饰的方法
}
同时除了增强注解的名称不同外,@AfterRuturning多了参数方法的返回值参数(对应其可以获取目标方法的返回值),@AfterThrowing多了异常参数(对应其可以获取目标方法的异常信息)
注:目标方法的异常必须为@AfterThrowing的异常及其子类,否则无法获取其信息
联系
由上面实例可知,所有的增强注释都有同样的切入点公式,即execution(返回值类型 目标方法名或目标类路径加名或注释(…))
并且其方法参数joinPoint的方法
Object target=joinPoint.getTarget();
String methodName = joinPoint.getSignature().getName();
Object[] params = joinPoint.getArgs();
都通用。