AOP
AOP: 面向切面编程, AOP对OOP补充, OOP: 宏观层面的思想, 对项目的整体的架构, AOP: 站在方法层面, 不改变原来的代码基础,动态增强原来的方法
面向切面编程,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术,
OOP: 面向对象编程
![]()
主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。
AOP好处:
在不改变核心代码的前提, 动态的添加额外的功能
业务逻辑与非业务逻辑的解耦
程序员专心负责某一功能
业务与非业务功能灵活组装(通过配置文件组装)
AOP基于xml方式:
导入aop相关依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!--spring-aop在spring-context已经传递--> <!--aspectJ的依赖: 会在spring-aspects传递--> <!-- <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency>--> <!--spring整合aspectJ的依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.36</version> </dependency>
编写通知类, (5种增强) 一个普通类
在Spring的配置文件中配置
把通知类交给spring管理
@Component("bizLogger") public class BizLogger {
在spring配置文件中配置aop相关配置
<!--把增强类(通知类)与目标类进行织入 --> <aop:config> <!--切入点: 对那些类那些方法进行增强 属性: id: 唯一标志符 public void com.fs.aop.service.impl.UserServiceImpl.addUser(参数列表) throws Exception public void com.fs.aop.service.impl.*.*(..) throws Exception expression:表达式 切入点表达式 语法: execution(修饰符? 返回值 方法名(参数) 异常?) 语法: ?: 0次或者1次 通配符: *: 任意 ..:参数列表中使用, 任意多个任意类型的参数 --> <aop:pointcut id="pointcut1" expression="execution(* com.fs.aop.service..*.*(..))"/> <!--织入 通知类方法与目标方法进行组装 5类通知: 前置通知 --> <!--通知类 ref: 通知类的bean的id --> <!--基于AspectJ的配置--> <aop:aspect ref="bizLogger"> <!--前置通知 method: 通知类的那个方法作为前置通知, 方法名 pointcut-ref: 切入点的id --> <!-- <aop:before method="before" pointcut-ref="pointcut1"></aop:before>--> <!--后置通知: 目标方法正常执行之后,返回结果 的增强 returning: 把目标方法的返回值 赋值给afterReturning那个参数, 参数名 --> <!-- <aop:after-returning returning="result" method="afterReturning" pointcut-ref="pointcut1"></aop:after-returning>--> <!--最终增强--> <!--<aop:after method="after" pointcut-ref="pointcut1"></aop:after>--> <!--异常增强 throwing: 把目标方法抛出异常对象赋值给增强方法那个参数接收 参数名 --> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut1" throwing="e"></aop:after-throwing> <!--环绕增强--> <aop:around method="aroundLogger" pointcut-ref="pointcut1"></aop:around> </aop:aspect> </aop:config>
基于注解的方式:
在通知类添加一个注解,表示它是通知类 @Aspect
在增强方法上添加对应的增强类型注解 @Before()
package com.fs.aop.log; import java.sql.SQLException; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /** * 日志增强类 */ @Slf4j @Component("bizLogger") @Aspect //表示该类是一个通知类 public class BizLogger { /** * 前置增强 * JoinPoint: 连接点 addUser()方法对象 * UserServiceImpl的addUser(User user) * getTarget(): 目标方法的目标对象 UserServiceImpl对象 * getSignature(): 目标方法 addUser() * getArgs(): 目标方法的参数的值 * @param jp */ @Before("execution(* com.fs.aop.service..*.*(..))") public void before(JoinPoint jp){ log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName() +"方法,传递的参数:"+Arrays.toString(jp.getArgs())); } /** * 后置增强 * @param jp * @param result 返回值 */ @AfterReturning(value = "execution(* com.fs.aop.service..*.*(..))",returning = "result") public void afterReturning(JoinPoint jp,Object result){ log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName() +"方法,方法的返回值:"+result); } /** * 异常增强 * @param jp * @param e 增强的异常类型 * SQLException: 这个异常增强只对目标方法抛出异常对象类型SQLException以及子类才执行 */ @AfterThrowing(value = "execution(* com.fs.aop.service..*.*(..))",throwing = "e") public void afterThrowing(JoinPoint jp,Exception e){ log.error("调用"+jp.getTarget()+"的"+jp.getSignature().getName() +"方法发生异常"+e); } /** * 最终增强 * @param jp */ @After("execution(* com.fs.aop.service..*.*(..))") public void after(JoinPoint jp){ log.info(jp.getSignature().getName()+"方法执行结束"); } /** * 环绕增强 * @param jp * ProceedingJoinPoint是JoinPoint子类 * proceed()方法: 调用这个方法, 调用目标方法, 没有调用, 目标方法都不执行 * @throws Throwable */ @Around("execution(* com.fs.aop.service..*.*(..))") public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable{ log.info(jp.getSignature().getName()+"方法开始执行"); try { //执行目标方法 Object rs = jp.proceed(); log.info(jp.getSignature().getName()+"方法正常执行完"); return rs; } catch (Exception e) { log.error("调用"+jp.getTarget()+"的"+jp.getSignature().getName() +"方法发生异常"+e); throw e; }finally { log.info(jp.getSignature().getName()+"方法执行完"); } } }
找spring配置文件,开启ApectJ的注解支持
<!--开启aspectJ注解扫描--> <aop:aspectj-autoproxy/>