美文网首页
Spring中AOP思想

Spring中AOP思想

作者: kjy_112233 | 来源:发表于2022-05-19 16:39 被阅读0次

    一、AOP基础

    导入aspect包

        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.9.4</version>
        </dependency>
    

    创建切面类设置

    @Configuration
    @ComponentScan("com.lijun")
    @EnableAspectJAutoProxy //开启注解开发AOP功能
    public class SpringConfig {
    }
    
    @Component
    @Aspect //设置当前类为切面类类
    public class MyAdvice {
        //设置切入点,要求配置在方法上方
        @Pointcut("execution(void com.lijun.dao.BookDao.update())")
        private void pt(){}
    
        //设置在切入点pt()的前面运行当前操作(前置通知)
        @Before("pt()")
        public void method(){
            System.out.println(System.currentTimeMillis());
        }
    }
    

    切入点表达式

    @Pointcut("execution(void com.lijun.dao.BookDao.update())")
    @Pointcut("execution(void com.lijun.dao.impl.BookDaoImpl.update())")
    @Pointcut("execution(* com.lijun.dao.impl.BookDaoImpl.update(*))") 
    @Pointcut("execution(void com.*.*.*.update())")
    @Pointcut("execution(* *..*(..))")
    @Pointcut("execution(* *..*e(..))")
    @Pointcut("execution(void com..*())")
    @Pointcut("execution(* com.lijun.*.*Service.find*(..))")
    

    通知类型

    public class MyAdvice {
        @Pointcut("execution(void com.lijun.dao.BookDao.update())")
        private void pt(){}
        @Pointcut("execution(int com.lijun.dao.BookDao.select())")
        private void pt2(){}
    
        //@Before:前置通知,在原始方法运行之前执行
        @Before("pt()")
        public void before() {
            System.out.println("before advice ...");
        }
    
        //@After:后置通知,在原始方法运行之后执行
        @After("pt2()")
        public void after() {
            System.out.println("after advice ...");
        }
    
        //@Around:环绕通知,在原始方法运行的前后执行
        @Around("pt2()")
        public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("around before advice ...");
            //表示对原始操作的调用
            Integer ret = (Integer) pjp.proceed();
            System.out.println("around after advice ...");
            return ret;
        }
    
        //@AfterReturning:返回后通知,在原始方法执行完毕后运行,且原始方法执行过程中未出现异常现象
        @AfterReturning("pt2()")
        public void afterReturning() {
            System.out.println("afterReturning advice ...");
        }
    
        //@AfterThrowing:抛出异常后通知,在原始方法执行过程中出现异常后运行
        @AfterThrowing("pt2()")
        public void afterThrowing() {
            System.out.println("afterThrowing advice ...");
        }
    }
    

    二、案例实现

    1、实现监听业务层运行时间
    @Component
    @Aspect
    public class ProjectAdvice {
        //匹配业务层的所有方法
        @Pointcut("execution(* com.lijun.service.*Service.*(..))")
        private void servicePt(){}
    
        //设置环绕通知,在原始操作的运行前后记录执行时间
        @Around("ProjectAdvice.servicePt()")
        public void runSpeed(ProceedingJoinPoint pjp) throws Throwable {
            //获取执行的签名对象
            Signature signature = pjp.getSignature();
            String className = signature.getDeclaringTypeName();
            String methodName = signature.getName();
    
            long start = System.currentTimeMillis();
            for (int i = 0; i < 10000; i++) {
               pjp.proceed();
            }
            long end = System.currentTimeMillis();
            System.out.println("万次执行:"+ className+"."+methodName+"---->" +(end-start) + "ms");
        }
    }
    
    2、通知获取数据(参数、返回值、异常)
    @Component
    @Aspect
    public class MyAdvice {
        @Pointcut("execution(* com.itheima.dao.BookDao.findName(..))")
        private void pt(){}
    
        //JoinPoint:用于描述切入点的对象,必须配置成通知方法中的第一个参数,可用于获取原始方法调用的参数
        @Before("pt()")
        public void before(JoinPoint jp) {
            Object[] args = jp.getArgs();
            System.out.println(Arrays.toString(args));
            System.out.println("before advice ..." );
        }
    
        @After("pt()")
        public void after(JoinPoint jp) {
            Object[] args = jp.getArgs();
            System.out.println(Arrays.toString(args));
            System.out.println("after advice ...");
        }
    
        //ProceedingJoinPoint:专用于环绕通知,是JoinPoint子类,可以实现对原始方法的调用
        @Around("pt()")
        public Object around(ProceedingJoinPoint pjp) {
            Object[] args = pjp.getArgs();
            System.out.println(Arrays.toString(args));
            args[0] = 666;
            Object ret = null;
            try {
                ret = pjp.proceed(args);
            } catch (Throwable t) {
                t.printStackTrace();
            }
            return ret;
        }
    
        //设置返回后通知获取原始方法的返回值,要求returning属性值必须与方法形参名相同
        @AfterReturning(value = "pt()",returning = "ret")
        public void afterReturning(JoinPoint jp,String ret) {
            System.out.println("afterReturning advice ..."+ret);
        }
    
        //设置抛出异常后通知获取原始方法运行时抛出的异常对象,要求throwing属性值必须与方法形参名相同
        @AfterThrowing(value = "pt()",throwing = "t")
        public void afterThrowing(Throwable t) {
            System.out.println("afterThrowing advice ..."+t);
        }
    }
    

    相关文章

      网友评论

          本文标题:Spring中AOP思想

          本文链接:https://www.haomeiwen.com/subject/wqutprtx.html