Springboot 中AOP的使用
面向切面编程(aspect oriented programming) 是软件编程思想发展到一定阶段的产物,是面向对象编程的有益补充。aop一般适用于具有横切逻辑的场合,如访问控制、事务管理、性能检测等。
日志、异常处理、事务控制等都是一个健壮的业务系统所必须的。但是为了保证系统健壮可用,就要再众多业务方法中反复编写类似的代码,使得原本就很复杂的业务处理代码变得更加复杂。业务功能的开发者还要考两次这些额外的代码是否处理正确,是否有遗漏的地方,如果需要修改日志信息的格式或者安全验证的规则,或者再增加辅助功能,都会导致业务代码频繁而大量的修改。
面向切面编程,就是在不改变原程序的基础上为代码增加新的功能,对代码段进行增强处理。他的设计思想来源于代理设计模式。
1.在原对象方法之前插入的增强处理为前置增强
2.该方法执行完以后插入的增强处理为后置增强
3.环绕在方法前后的增强处理为环绕增强,是最强大的增强处理,可以获取或者修改目标方法的参数、返回值、异常处理、甚至决定目标方法是否执行。
4.该方法抛出异常时的增强处理为异常抛出增强
5.最终增强处理,无论方法抛出异常还是正常退出都会得到执行,类似于异常处理机制中finally块的作用,一般用于释放资源
在springboot中使用注解
需要引入所需要的jar :spring-boot-starter-aop
创建一个aop增强处理类
@slf4j @aspect @component public class loggeraspect { // 匹配 com.lzz.lzzapp.common.user包及子包下所有类的所有方法 @pointcut("execution(* com.lzz.lzzapp.common.user..*.*(..))") public void logpointcut(){ } //前置增强 在连接点执行之前执行的通知 @before("logpointcut()") public void before(){ log.info("即将调用业务方法"); } //最终增强 在连接点执行之后执行的通知(返回通知和异常通知的异常) @after("logpointcut()") public void after(){ log.info("业务方法调用完成"); } /** * 后置增强 在连接点执行之后执行的通知(返回通知) */ @afterreturning(value="logpointcut()",returning="result") public void doafterreturning(joinpoint joinpoint, object result){ string methodname = joinpoint.getsignature().getname(); log.info("调用"+joinpoint.gettarget()+"的"+methodname+"方法。参数:"+arrays.tostring(joinpoint.getargs()) +"。方法返回值:"+result); } /** * 异常增强 在连接点执行之后执行的通知(异常通知) */ @afterthrowing("logpointcut()") public void doafterthrowing(){ log.info("异常处理完成"); } /** * 环绕增强 */ @around("logpointcut()") public void doaround(proceedingjoinpoint jp){ log.info("调用"+jp.gettarget()+"的"+jp.getsignature().getname()+"方法。参数:"+arrays.tostring(jp.getargs())); try { object result=jp.proceed();//执行目标方法 log.info("方法返回值:"+result); }catch (throwable e){ log.error(jp.getsignature().getname()+"方法发生异常"); e.printstacktrace(); } } }
使用@aspect定义切面,@pointcut定义切入点
切入点匹配的执行点为连接点为jointpoint,spring会自动注入该实例,通过joinpoint 的gettarget()方法可以得到被代理对象,getsignature()方法返回被代理的目标方法。getargs()方法返回传递给目标方法的参数数组
对于后置增强,还可以定义一个用于接收被代理方法的返回值,必须在 @afterreturning 注解中通过returning 属性指定该参数的名称
execution是切入点指示符,他括号中是一个切入点表达式,可以配置要切入的方法,切入点表达式支持模糊匹配
public * adduser(com.entity.user) * 表示匹配所有类型的返回值 public void *(com.entity.user) * 表示匹配所有方法名 public void adduser(..) .. 表示匹配所有参数个数和类型 * com.user.*.*(..) 表示匹配com.entity包下所有类的所有方法 * com.user..*.*(..) 表示匹配com.entity包及其子包下所有类的所有方法