(1)[
掌握
]@AfterReturning
后置通知
-
注解有
returning
属性
在目标方法执行之后执行。由于是目标方法之后执行,所以可以获取到目标方法的返回
值。该注解的
returning
属性就是用于指定接收方法返回值的变量名的。所以,被注解为后
置通知的方法,除了可以包含
JoinPoint
参数外,还可以包含用于接收返回值的变量。该变
量最好为
Object
类型,因为目标方法的返回值可能是任何类型。
接口增加方法:
package com.zsz.ba02;
public interface SomeService {
void doSome(String name, Integer age);
//新增
String doOther (String name, Integer age);
}
实现方法:
@Override
public String doOther(String name, Integer age) {
System.out.println("===目标方法doOther===");
return "abcd";
}
定义切面:
package com.zsz.ba02;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
/**
* @Aspect:是aspectj框架中的注解。
*
* 作用:表示当前类是切面类。
* 切面类是用来给业务方法增加功能的类,在这个类中有切面的功能代码
* 位置:在类定义的上面
*/
@Aspect
public class MyAspect {
// 后置通知定义方法
/**
* @AfterReturning:后置通知
* 属性:1.value 切入点表达式
* 2.returning 自定义的变量,表示目标方法的返回值的。
* 自定义变量名必须和通知方法的形参名一样。
*
*
*/
@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",returning = "res")
public void myAfterReturning (Object res){
//Object res:是目标方法执行后的返回值,根据返回值做你的切面的功能处理
System.out.println("后置通知:在目标方法之后执行的,获取的返回值是:"+res);
}
}
(2)[掌握]@Around 环绕通知-增强方法有 ProceedingJoinPoint 参数
在目标方法执行之前之后执行。被注解为环绕增强的方法要有返回值,
Object
类型。并
且方法可以包含一个
ProceedingJoinPoint
类型的参数。接口
ProceedingJoinPoint
其有一个
proceed()
方法,用于执行目标方法。若目标方法有返回值,则该方法的返回值就是目标方法
的返回值。最后,环绕增强方法将其返回值返回。该增强方法实际是拦截了目标方法的执行。
接口增加方法:
package com.zsz.ba03;
public interface SomeService {
void doSome(String name, Integer age);
String doOther(String name, Integer age);
//新增
String doFirst(String name,Integer age);
}
接口方法的实现:
@Override
public String doFirst(String name, Integer age) {
System.out.println("===业务方法doFirst()===");
return "doFirst";
}
定义切面:
package com.zsz.ba03;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import java.util.Date;
/**
* @Aspect:是aspectj框架中的注解。
*
* 作用:表示当前类是切面类。
* 切面类是用来给业务方法增加功能的类,在这个类中有切面的功能代码
* 位置:在类定义的上面
*/
@Aspect
public class MyAspect {
/**
* 环绕通知方法的定义格式
* 1.public
* 2.必修一有一个返回值,推荐使用Object
* 3.方法名称自定义
* 4.方法有参数,固定的参数ProceedingJoinPoint
*
*
*/
/**
* @Around :环绕通知
* 属性: value 切入点表达式
* 位置:在方法的定义上面
*
* 特点:
* 1.他是功能最强的通知
* 2.在目标方法的前后都能增强功能
* 3.控制目标方法是否被调用执行
* 4.修改原来的目标方法的执行结果。影响最后的调用结果
*
* 环绕通知相当于jdk的动态代理,InvocationHandler接口
* 参数:ProceedingJoinPoint 等同于Method
* 作用执行目标方法
*
* 返回值:就是目标方法的执行结果,可以被修改
*
* 环绕通知:经常做事务,在目标方法之前开启事务,执行目标方法,在目标方法之后提交事务。
*
*/
@Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAround (ProceedingJoinPoint pjp) throws Throwable {
//实现环绕通知
Object result=null;
System.out.println("环绕通知:在目标方法之前,输出时间:"+new Date());
//1.目标方法调用
result=pjp.proceed();//等同于method.invoke(); Object result=doFirst();
System.out.println("环绕通知:在目标方法之后,提交事务");
return result;
}
}
(3)
[
了解
]@AfterThrowing
异常通知
-
注解中有
throwing
属性
在目标方法抛出异常后执行。该注解的
throwing
属性用于指定所发生的异常类对象。
当然,被注解为异常通知的方法可以包含一个参数
Throwable
,参数名称为
throwing
指定的
名称,表示发生的异常对象。
增加业务方法:
方法实现:
定义切面:
(4)[
了解
]@After
最终通知
无论目标方法是否抛出异常,该增强均会被执行。
增加方法:
方法实现:
定义切面:
(5)
@Pointcut
定义切入点
当较多的通知增强方法使用相同的
execution
切入点表达式时,编写、维护均较为麻烦。
AspectJ
提供了
@Pointcut
注解,用于定义
execution
切入点表达式。
其用法是,将
@Pointcut
注解在一个方法之上,以后所有的
execution
的
value
属性值均
可使用该方法名作为切入点。代表的就是
@Pointcut
定义的切入点。这个使用
@Pointcut
注解
的方法一般使用
private
的标识方法,即没有实际作用的方法。
package com.zsz.ba06;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspect {
@After(value = "mypt()")
public void myAfter () {
System.out.println("执行最终通知,总是会被执行的代码");
}
@Before(value = "mypt()")
public void myBefor() {
System.out.println("前置通知,在目标方法之前执行");
}
/**
* @PointCut:定义和管理切入点,如果你的项目中有多个切入点表达式是重复的,可以复用的。
* 可以使用@PointCut
*
* 属性:value 切入点表达式
* 位置:在自定义的方法上面
*
* 特点:
* 当使用@Pointcut定义在一个方法的上面,此时这个方法的名称就是切入点表达式的别名。
* 其他的通知中,value属性就可以使用这个方法名称,代替切入点表达式了
*/
@Pointcut(value = "execution(* *..SomeServiceImpl.doThird(..))")
private void mypt(){
}
}
好了Aop整完了。