spring aop 实现 www why when how
详解参照 https://www.cnblogs.com/lidj/p/7194193.html
what aop基本概念:面向切面编程,关注点:切点、切点函数参数、切面返回值、切面执行顺序
注意:切面编程是同步执行的,执行顺序一般为 around->befor->around->after->after-returning
when、where 应用场景:事务、日志、持久化、监控、异常处理等
how 有如下几种实现方式:
一、XML配置的Spring AOP
1. 该示例配置参数比较完整,有切点函数的返回值配置
<aop:config> <aop:pointcut id="subscibe" expression="execution(* com.tcms.service.modifyPageModules(..)) or execution(* com.tcms.service..modify(..))"/> <aop:aspect ref="subscibeService"> <aop:after-returning arg-names="joinPoint, retValue" returning="retValue" method="subscibeService" pointcut-ref="subscibe" /> </aop:aspect> </aop:config>
// 2. 方法实现
public class SubscibeService { public void subscibeService(JoinPoint joinPoint, Object retValue){ Object[] params = joinPoint.getArgs(); log.info("请求返回值为:request={}", JsonUtil.toString(params)); log.info("请求返回值为:retValue={}", JsonUtil.toString(retValue)); } }
二、AspectJ切点函数
aop 指示器详解参考地址 :https://blog.csdn.net/sunlihuo/article/details/52701548
AspectJ 指示器
arg () 限制连接点的指定参数为指定类型的执行方法
@args () 限制连接点匹配参数由指定注解标注的执行方法
execution () 用于匹配连接点的执行方法(可以到切点方法)
this () 限制连接点匹配 AOP 代理的 Bean 引用为指定类型的类
target () 限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型注解
within() 限制连接点匹配指定类型(类)
@within() 限制连接点匹配指定注释所标注的类型(当使用 Spring AOP 时,方法定义在由指定的注解所标注的类里)
@annotation 限制匹配带有指定注释的连接点
package com.learn.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class HelloServiceAop { //匹配com.learn.service.impl包及其子包下的所有类的所有方法 @Pointcut("execution(* com.learn.service.impl.*.*(..))") public void executeService(){ } @Before("executeService()") public void doBeforeAdvice(JoinPoint joinPoint){ System.out.println("我是前置通知!!!"); //获取目标方法的参数信息 Object[] obj = joinPoint.getArgs(); System.out.println(obj); //AOP代理类的信息 joinPoint.getThis(); //代理的目标对象 joinPoint.getTarget(); //用的最多 通知的签名 Signature signature = joinPoint.getSignature(); //代理的是哪一个方法 System.out.println(signature.getName()); //AOP代理类的名字 System.out.println(signature.getDeclaringTypeName()); //AOP代理类的类(class)信息 System.out.println(signature.getDeclaringType()); } }
三、注解实现方式
// 1、添加注解 @Inherited @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface LogAnnotation { String desc() default "打印日志"; } // 2、切点执行操作 package com.learn.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component public class LogAspect { public void addLogSuccess(JoinPoint jp) { Object[] parames = jp.getArgs();//获取目标方法体参数 for (int i = 0; i < parames.length; i++) { System.out.println(parames[i]); } System.out.println(jp.getSignature().getName()); String className = jp.getTarget().getClass().toString();//获取目标类名 System.out.println("className:" + className); className = className.substring(className.indexOf("com")); String signature = jp.getSignature().toString();//获取目标方法签名 System.out.println("signature:" + signature); } }
3、xml 配置
<aop:config> <aop:pointcut id="aspect" expression="@annotation(com.tiefan.smm.order.support.aop.LogAnnotation)"/> <aop:aspect ref="logAspect"> <aop:around method="addLogSuccess" pointcut-ref="aspect"/> </aop:aspect> </aop:config>
4、在切点方法上添加注解