以下内容转自:https://www.cnblogs.com/lixiang1993/p/7447853.html
1.声明一个切面类,并把这个切面类加入到IOC容器中
@Component
@Aspect
public class LogAspect{
@Pointcut(value="execution(* *.*(..))")
public void showLog(){}
@Before(value="showLog()")
public void showBeginLog(){
System.out.println("AOP日志开始");
}
@After(value="showLog()")
public void showReturnLog(){
System.out.println("AOP方法结束");
}
@AfterThrowing(value="showLog()")
public void showExceptionLog(){
System.out.println("AOP方法异常");
}
@AfterReturning(value="showLog()")
public void showAfterLog(){
System.out.println("AOP方法最终返回");
}
}
2.被代理的对象也需要加入IOC容器
@Component
public class MathCalculator {
public void add(int i, int j) {
int result=i+j;
System.out.println("目标方法add(int)执行了");
}
public void sub(int i, int j) {
int result=i-j;
System.out.println("目标方法sub执行了");
}
public void mult(int i, int j) {
int result=i*j;
System.out.println("目标方法mult执行了");
}
public void div(int i, int j) {
int result=i/j;
System.out.println("目标方法div执行了");
}
}
3.切入点表达式
- 切入点表达式的语法格式
execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表]))
- 切入点表达式支持通配符
- 两种切入表达式
- 最详细的切入点表达式:
execution(public void com.bwlu.aop.MathCalculator.add(int, int))
-
- 最模糊的切入点表达式:
execution (* *.*(..))
execution(public void com.bwlu.aop.MathCalculator.add(int, int)):只有add方法加入了4个通知,
execution(public void com.bwlu.aop.MathCalculator.*(int, int)):任意方法,参数为int,int
execution(public void com.bwlu.aop.MathCalculator.*(..)):MathCalculator中的任意方法,任意参数列表
execution(public * com.bwlu.aop.MathCalculator.*(..)):MathCalculator中的任意方法,任意参数列表,任意返回值
execution( * com.bwlu.aop.MathCalculator.*(..)):MathCalculator中的任意方法,任意参数列表,任意返回值,任意访问修饰符
execution (* *.*(..)):任意匹配
需要注意的是:权限是不支持写通配符的,当然你可以写一个*表示所有权限所有返回值!
4.通知方法的细节
(1)在通知中获取目标方法的方法名和参数列表
- 在通知方法中声明一个JoinPoint类型的形参
- 调用JoinPoint对象的getSignature()方法获取目标方法的签名
- 调用JoinPoint对象的getArgs()方法获取目标方法的实际参数列表
(2)在返回通知中获取方法的返回值
- 在@AfterReturning注解中添加returning属性:@AfterReturning (value="showLog()", returning= "result")
- 在返回通知的通知方法中声明一个形参,形参名和returning属性的值一致:showReturnLog(JoinPoint joinPoint, Object result)
(3)在异常通知中获取异常对象
- 在@ AfterThrowing注解中添加throwing属性:@AfterThrowing (value="showLog()",throwing= "throwable" )
- 在异常通知的通知方法中声明一个形参,形参名和throwing属性值一致:showExceptinLog(JoinPoint joinPoint, Throwable throwable)
@Aspect
public class LogAspect{
@Pointcut(value="execution(* *.*(..))")
public void showLog(){}
@Before(value="showLog()")
public void showBeginLog(JoinPoint jPoint){
Object[] args = jPoint.getArgs();
List<Object> asList = Arrays.asList(args);
Signature signature = jPoint.getSignature();
String name = signature.getName();
System.out.println("AOP日志开始");
System.out.println("目标方法名:"+name+",参数列表:"+asList);
}
@After(value="showLog()")
public void showReturnLog(){
System.out.println("AOP方法结束");
}
@AfterThrowing(value="showLog()",throwing="ex")
public void showExceptionLog(Exception ex){
System.out.println("AOP方法异常");
System.out.println("异常信息:"+ex.getMessage());
}
@AfterReturning(value="showLog()",returning="result")
public void showAfterLog(Object result){
System.out.println("方法返回值:"+result);
System.out.println("AOP方法最终返回");
}
}
5.环绕通知@Around
环绕通知需要在方法的参数中指定JoinPoint的子接口类型ProceedingJoinPoint为参数:
public void around(ProceedingJoinPoint joinPoint){}
环绕通知能够替代其他4个通知。
注意:@Around修饰的方法一定要将方法的返回值返回!本身相当于代理!
@Aspect
public class LogAspect{
@Around(value="execution(* *.*(..))")
public Object showLog(ProceedingJoinPoint point){
Object[] args = point.getArgs();
List<Object> asList = Arrays.asList(args);
Signature signature = point.getSignature();
String name = signature.getName();
Object result = null;
try {
try {
//目标方法之前要执行的操作,相当于@before
System.out.println("[环绕日志]"+name+"开始了,参数为:"+asList);
//调用目标方法
result = point.proceed(args);
} finally {
//方法最终结束时执行的操作,相当于@after
System.out.println("[环绕日志]"+name+"结束了!");
}
//目标方法正常执行之后的操作,相当于@AfterReturning
System.out.println("[环绕日志]"+name+"返回了,返回值为:"+result);
} catch (Throwable e) {
//目标方法抛出异常信息之后的操作,相当于@AfterThrowing
System.out.println("[环绕日志]"+name+"出异常了,异常对象为:"+e);
throw new RuntimeException(e.getMessage());
}
return result;
}
}
6、切面的优先级
对于同一个代理对象,可以同时有多个切面共同对它进行代理。
可以在切面类上通过@Order (value=50)注解来进行设置,值越小优先级越高!
@Aspect
@Component
@Order(value=40)
public class LogAspect {}
明天再加日志配置说明,洗洗睡了先