Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 372|回复: 0

AOP基础:注解方式实现前置通知、后置通知、环绕通知、异常通知、最终通知(demo)

[复制链接]
  • TA的每日心情
    奋斗
    昨天 22:25
  • 签到天数: 790 天

    [LV.10]以坛为家III

    2049

    主题

    2107

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    722766
    发表于 2021-5-1 16:46:53 | 显示全部楼层 |阅读模式

    除了使用xml配置外,还可以使用注解的方式实现上述几种通知。

     

    LogAspectAnnotation.java:

    package aop.Aspe;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    
    @Component("logAnn")
    @Aspect
    public class LogAspectAnnotation {
        @Before("execution(public * springProject.Student.add(..))")
        public void bBefore() {
            System.out.println("@@@前置通知");
        }
        @AfterReturning("execution(public * springProject.Student.add(..))")
        public void bAfter() {
            System.out.println("@@@后置通知");
        }
        @AfterThrowing("execution(public * springProject.Student.add(..))")
        public void bThrowing() {
            System.out.println("@@@异常通知");
        }
        
        //环绕通知 ,参数ProceedingJoinPoint
        @Around("execution(public * springProject.Student.add(..))")
        public void myAround(ProceedingJoinPoint jp  ) {
            //方法之前:前置通知
            System.out.println("《【环绕】方法之前:前置通知");
            
            try {
                //方法执行时
                jp.proceed() ;//执行方法
        
                //方法之前之后:后置通知
                System.out.println("《【环绕】方法之前之后:后置通知");
            }catch(Throwable e) {
                //发生异常时:异常通知
                System.out.println("《【环绕】发生异常时:异常通知");
            }finally {
                //最终通知
                System.out.println("《【环绕】最终通知");
            }
        }
    }

     

    tips:

    @Component("logAnn"): 把这个类加入ioc容器,id为logAnn。
        必须在xml中,加入xmlns:context="http://www.springframework.org/schema/context"
        然后调用扫描器:<context:component-scan base-package="aop.Aspe"></context:component-scan>
        扫描器 会将 指定的包 中的  @Componet @Service  @Respository   @Controller修饰的类产生的对象 增加到IOC容器中

    @Aspect:  声明这个类是个通知。
           不需要通过扫描器,只需要在xml文件中开启即可:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    @Before("execution(public * springProject.Student.add(..))")
           声明这个方法是个前置通知,关联的业务方法为add。

    @AfterReturning("execution(public * springProject.Student.add(..))")
           
    声明这个方法是个前置通知,关联的业务方法为add。

    @AfterThrowing("execution(public * springProject.Student.add(..))")  
           声明这个方法是个异常通知。
    @Around("execution(public * springProject.Student.add(..))")
           声明这个方法为环绕通知。

    上述各个通知对应的方法名可以随便取。


    如果想要获取目标对象的一些参数,则需要使用一个对象:JointPoint。

    package org.lanqiao.aop;
    
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    //<bean id="logAnnotation" class="org.lanqiao.aop.LogAspectAnnotation">
    //@Component("logAnnotation")   //将LogAspectAnnotation纳入springIOC容器中
    @Aspect //此类是一个通知
    public class LogAspectAnnotation  {
        
        //前置通知
        @Before("execution(public * addStudent(..))") //属性:定义切点
        public void myBefore(JoinPoint jp) {
            System.out.println("《注解形式-前置通知》:目标对象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName() +",参数列表:"+ jp.getArgs().length  );
        }
        //后置通知
        @AfterReturning( pointcut= "execution(public * addStudent(..))" ,returning="returningValue" ) 
        public void myAfter(JoinPoint jp,Object returningValue) {//returningValue是返回值,但需要告诉spring
            System.out.println("《注解形式-后置通知》:目标对象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName() +",参数列表:"+  jp.getArgs().length+",返回值:"+returningValue );
        }
        
        /*环绕通知 ,参数ProceedingJoinPoint
        @Around("execution(public * addStudent(..))")
        public void myAround(ProceedingJoinPoint jp  ) {
            //方法之前:前置通知
            System.out.println("《【环绕】方法之前:前置通知");
            
            try {
                //方法执行时
                jp.proceed() ;//执行方法
        
                //方法之前之后:后置通知
                System.out.println("《【环绕】方法之前之后:后置通知");
            }catch(Throwable e) {
                //发生异常时:异常通知
                System.out.println("《【环绕】发生异常时:异常通知");
            }finally {
                //最终通知
                System.out.println("《【环绕】最终通知");
            }
        }*/
        
        //异常通知:如果只捕获特定类型的已存银行,则可以通过第二个参数实现:e
        @AfterThrowing(pointcut= "execution(public * addStudent(..))",throwing="e")
        public void myException(JoinPoint pj, NullPointerException e) {//此异常通知 只会捕获NullPointerException类型的异常
            System.out.println("&&&&&&《注解形式-异常通知》----e:"+e.getMessage());
        }
        
        //最终通知
        @After("execution(public * addStudent(..))")
        public void myAfter() {
            System.out.println("《[myAfter]注解形式-最终通知-----通知》----");
        }
        
        
    }
     
    

    注解形式的返回值:
    a.声明返回值 的参数名:
      

    @AfterReturning( pointcut= "execution(public * addStudent(..))" ,returning="returningValue" ) 
        public void myAfter(JoinPoint jp,Object returningValue) {//returningValue是返回值,但需要告诉spring
        System.out.println("返回值:"+returningValue );

     

    b: 注解形式实现aop时,通知的方法的参数不能多、少。

    c: 实现接口形式、注解形式 只捕获声明的特定类型的异常,而其他类型异常不捕获。

    d: 异常通知,可以只在某个特定异常才输出。

    @AfterThrowing(pointcut= "execution(public * addStudent(..))",throwing="e")
      public void myException(JoinPoint pj, NullPointerException e) {//此异常通知 只会捕获NullPointerException类型的异常
      System.out.println("&&&&&&《注解形式-异常通知》----e:"+e.getMessage());
    }

     

     

     
     
     
    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-9-11 23:02 , Processed in 0.085849 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表