第4节 Spring中AOP实现
需求:横切逻辑代码是打印⽇志,希望把打印⽇志的逻辑织⼊到⽬标⽅法的特定位置 (service 层 transfer ⽅法 )4.1 XML 模式
Spring 是模块化开发的框架,使⽤ aop 就引⼊ aop 的 jar<!--spring aop的jar包支持--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.1.12.RELEASE</version> </dependency> <!--第三方的aop框架aspectj的jar--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency>
创建横切逻辑代码
package com.lagou.edu.utils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; public class LogUtils { /** * 业务逻辑开始之前执行 */ public void beforeMethod(JoinPoint joinPoint) { System.out.println("业务逻辑开始执行之前执行......."); } /** * 业务逻辑结束时执行(无论异常与否) */ public void afterMethod() { System.out.println("业务逻辑结束时执行,无论异常与否都执行......."); } /** * 异常时时执行 */ public void exceptionMethod() { System.out.println("异常时执行......."); } /** * 业务逻辑正常时执行 */ public void successMethod(Object retVal) { System.out.println("业务逻辑正常时执行......."); } }
<!--进行aop相关的xml配置,配置aop的过程其实就是把aop相关术语落地--> <!--横切逻辑bean--> <!--<bean id="logUtils" class="com.lagou.edu.utils.LogUtils"></bean> <!–使用config标签表明开始aop配置,在内部配置切面aspect–> <!–aspect = 切入点(锁定方法) + 方位点(锁定方法中的特殊时机)+ 横切逻辑 –> <aop:config> <aop:aspect id="logAspect" ref="logUtils"> <!–切入点锁定我们感兴趣的方法,使用aspectj语法表达式–> <!–<aop:pointcut id="pt1" expression="execution(* *..*.*(..))"/>–> <aop:pointcut id="pt1" expression="execution(* com.lagou.edu.service.impl.TransferServiceImpl.*(..))"/> <!–方位信息,pointcut-ref关联切入点–> <!–aop:before前置通知/增强–> <aop:before method="beforeMethod" pointcut-ref="pt1"/> </aop:aspect>
测试:
/** * 测试xml aop */ @Test public void testXmlAop() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); TransferService transferService = applicationContext.getBean(TransferService.class); transferService.transfer("6029621011000","6029621011001",100); }
结果:
获取一些参数,能够获取方法传入的参数 public void beforeMethod(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); for (int i = 0; i < args.length; i++) { Object arg = args[i]; System.out.println(arg); } System.out.println("业务逻辑开始执行之前执行......."); }
加入环绕通知
/** * 环绕通知 * */ /*@Around("pt1()")*/ public Object arroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕通知中的beforemethod...."); Object result = null; try{ // 控制原有业务逻辑是否执行 // result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); }catch(Exception e) { System.out.println("环绕通知中的exceptionmethod...."); }finally { System.out.println("环绕通知中的after method...."); } return result; }