个人站长做什么类型的网站,做生存分析的网站有哪些,网站开发实例社区,小程序开发流程详解前言 AOP#xff0c;意为#xff1a;面向切面编程#xff0c;通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。基于AOP实现的功能不会破坏原来程序逻辑#xff0c;因此它可以很好的对业务逻辑的各个部分进行隔离#xff0c;从而使得业务逻辑各部分之间的…前言 AOP意为面向切面编程通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。基于AOP实现的功能不会破坏原来程序逻辑因此它可以很好的对业务逻辑的各个部分进行隔离从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性同时提高了开发的效率。 正文
Spring Boot 中使用
在 pom.xml 中加入 aop 依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency当我们需要在非接口上面进行切面操作的时候就需要 CGLIB来实现 AOP在系统配置文件中加入设置
spring: aop:proxy-target-class: true默认为 false。
切点表达式
列出常用的几个表达式 execution() 满足execution中描述的方法签名。 execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?) * modifier-pattern表示方法的修饰符; * ret-type-pattern表示方法的返回值 * declaring-type-pattern表示方法所在的类的路径 * name-pattern表示方法名 * param-pattern表示方法的参数 * throws-pattern表示方法抛出的异常 * 其中后面跟着?的是可选项。 this()是用来限定方法所属的类为接口则限定所有的实现类为类的话限定这单个类。 annotation表示具有某个标注的方法。 args 表示方法的参数属于一个特定的类args 表示参数有特定的标注注解。 within 包或者类型满足within中描述的包或者类型的类的所有非私有方法within 类型拥有target描述中给出的annotation,其中target和within的区别在于within要求的annotation的级别为CLASS而target为RUNTIME . target 业务实例对象非代理实例的类型满足target 中的描述的类型target 类型拥有target描述中给出的annotation bean() 表示所有匹配的 bean例如 ,bean(“*Service”)匹配所有 Service 结尾的类。可以使用 !bean() 表示不匹配。
注意事项: * 在各个pattern中可以使用”*”来表示匹配所有。 * 在param-pattern中可以指定具体的参数类型多个参数间用,隔开各个也可以用 * 来表示匹配任意类型的参数如(String)表示匹配一个String参数的方法(*,String)表示匹配有两个参数的方法第一个参数可以是任意类型而第二个参数是String类型。 * 可以用(..)表示零个或多个任意的方法参数。 * 使用符号表示与关系使用||表示或关系、使用!表示非关系。在XML文件中使用and、or和not这三个符号。
AspectJ提供了五种定义通知的标注
Before前置通知在调用目标方法之前执行通知定义的任务After后置通知在目标方法执行结束后无论执行结果如何都执行通知定义的任务AfterReturning后置通知在目标方法执行结束后如果执行成功则执行通知定义的任务AfterThrowing异常通知如果目标方法执行过程中抛出异常则执行通知定义的任务Around环绕通知在目标方法执行前和执行后都需要执行通知定义的任务
通过标注定义通知只需要两个步骤
将以上五种标注之一添加到切面的方法中在标注中设置切点的定义。
创建环绕通知
环绕通知相比其它四种通知有其特殊之处。环绕通知本质上是将前置通知、后置通知和异常通知整合成一个单独的通知。
用Around标注的方法该方法必须有一个ProceedingJoinPoint类型的参数
在方法体中需要通过这个参数以joinPoint.proceed();的形式调用目标方法。注意在环绕通知中必须进行该调用否则目标方法本身的执行就会被跳过。
计算方法的执行时间 Around(logPointCut()) //切点public Object around(ProceedingJoinPoint point) throws Throwable {long beginTime System.currentTimeMillis();//执行方法Object result point.proceed();//执行时长(毫秒)long time System.currentTimeMillis() - beginTime;return result;}处理通知中参数
获取参数的方式则需要使用关键词是args。 Pointcut(bean(sysUserServiceImpl) args(userEntity,..))public void userPointCut(SysUserEntity userEntity) {}Before(userPointCut(userEntity))public void validateUser(SysUserEntity userEntity) {// to handler args}这里有个非常严格的一点就是args(userEntity,..)表示目标方法可能有多个参数但是包括 userEntity这里 userEntity 必须参数名相同不同就编织了。
args()中参数的名称必须跟切点方法的签名中public void validateUser(SysUserEntity userEntity)的参数名称相同。如果使用切点函数定义其中的参数名称也必须与通知方法签名中的参数完全相同
AfterReturning增强处理 AfterReturning(pointcut logPointCut(), returning rtv)public void logAfter(Object rtv) {System.out.println(Objects.toString(rtv));}使用 AfterReturning 注解时指定了一个returning属性假设该属性值为rvt这表明允许在Advice方法logAfter()方法中定义名为rvt的形参程序可通过rvt形参来访问目标方法的返回值。
注意 虽然AfterReturning增强处理可以访问到方法的返回值但它不可以改变目标方法的返回值。
AOP切面的优先级
有时候我们对一个方法会有多个切面的问题这个时候还会涉及到切面的执行顺序的问题。
我们可以定义每个切面的优先级 Spring 中提供注解 Order(i) 当 i 的值越小优先级越高。
参考文章
Spring AOP中定义切点PointCut和通知AdviceSpring Boot中使用AOP统一处理Web请求日志