基于注解配置的AOP
在看这篇博文之前,建议先看下上一篇博文;地址
首先在Spring的xml文件中完成相应的配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置spring创建容器时要扫描的包--> <context:component-scan base-package="com.itheima"></context:component-scan> <!-- 配置spring开启注解AOP的支持 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
在持久化类中加上注解,方便使用id调用
注意这里设置了一个异常 1/0的异常
日志类的代码如下:
import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /** * 用于记录日志的工具类,它里面提供了公共的代码 */ @Component("logger") @Aspect//表示当前类是一个切面类 public class Logger { //设置切入点的表达式 // @Pointcut("execution(* com.itheima.service.impl.*.*(..))") private void pt1(){} //前置通知 @Before("execution(* com.itheima.service.impl.*.*(..))") public void beforePrintLog(){ System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了。。。"); } /** * 后置通知 */ @AfterReturning("execution(* com.itheima.service.impl.*.*(..))") public void afterReturningPrintLog(){ System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志了。。。"); } /** * 异常通知 */ @AfterThrowing("execution(* com.itheima.service.impl.*.*(..))") public void afterThrowingPrintLog(){ System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。"); } /** * 最终通知 */ @After("execution(* com.itheima.service.impl.*.*(..))") public void afterPrintLog(){ System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。"); } /** * 环绕通知 * 问题: * 当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了。 * 分析: * 通过对比动态代理中的环绕通知代码,发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有。 * 解决: * Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法。 * 该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。 * * spring中的环绕通知: * 它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。 */ /* @Around("pt1()") public Object aroundPringLog(ProceedingJoinPoint pjp){ Object rtValue = null; try{ Object[] args = pjp.getArgs();//得到方法执行所需的参数 System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置"); rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法) System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置"); return rtValue; }catch (Throwable t){ System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常"); throw new RuntimeException(t); }finally { System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终"); } }*/ }
如上图所示:需要注明类的名称以及切面类的的表示。同时在,每个环绕方法中设置切入点的表达式
执行结果如上图所示。显然成功了
同样的,在上一篇的博文中环绕通知可以通过aroud进行设置,在本篇博文中,我们同样可以通过设置环绕标签完成环绕通知的操作。
代码如下:
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * 用于记录日志的工具类,它里面提供了公共的代码 */ @Component("logger") @Aspect//表示当前类是一个切面类 public class Logger { //设置切入点的表达式 @Pointcut("execution(* com.itheima.service.impl.*.*(..))") /** * 环绕通知 * 问题: * 当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了。 * 分析: * 通过对比动态代理中的环绕通知代码,发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有。 * 解决: * Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法。 * 该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。 * * spring中的环绕通知: * 它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。 */ @Around("execution(* com.itheima.service.impl.*.*(..))") public Object aroundPringLog(ProceedingJoinPoint pjp){ Object rtValue = null; try{ Object[] args = pjp.getArgs();//得到方法执行所需的参数 System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置"); rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法) System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置"); return rtValue; }catch (Throwable t){ System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常"); throw new RuntimeException(t); }finally { System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终"); } } }
其他的一律不变
一纸高中万里风,寒窗读破华堂空。
莫道长安花看尽,由来枝叶几相同?