zoukankan      html  css  js  c++  java
  • Spring基础——AOP通知

    spring(AOP通知)

    切面

    切面是封装通用业务逻辑的组件,可以作用到其他组件上。是spring组件中的某个方法、无返回类型、参数类型与通知类型有关。
    一个切面 开启数据库 关闭数据库 开启事务 检查登录账号状态 监测账号权限

    切点

    用于指定哪些组件哪方法使用切面组件,Spring提供表达式来实现该制定。

    通知

    用于指定组件作用到目标组件的具体位置。

    连接点(Joinpoint)
      增强程序执行的某个特定位置(要在哪个地方做增强操作)。Spring仅支持方法的连接点,既仅能在方法调用前,方法调用后,方法抛出异常时等这些程序执行点进行织入增强。

    切点(Pointcut)
      切点是一组连接点的集合。AOP通过“切点”定位特定的连接点。通过数据库查询的概念来理解切点和连接点的关系再适合不过了:连接点相当于数据库中的记录,而切点相当于查询条件。

    增强(Advice)
      增强是织入到目标类连接点上的一段程序代码。表示要在连接点上做的操作。

    切面(Aspect)
      切面由切点和增强(引介)组成(可以包含多个切点和多个增强),它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的链接点中。

    注解使用

    @aspect 定义切面
    @pointcut 定义切点
    @before 标注Before Advice定义所在的方法
    @afterreturning 标注After Returning Advice定义所在的方法
    @afterthrowing 标注After Throwing Advice定义所在的方法
    @after 标注 After(Finally) Advice定义所在的方法
    @around 标注Around Advice定义所在的方法

    1.AOP通知(配置xml文件)

    QieMian1.java

    public class QieMian1 {
        public void qianzhi(JoinPoint jp) {
            System.out.println("前置通知");
            Object [] os = jp.getArgs();
            for (Object object : os) {
                System.out.println("参数列表为:"+object);
            }
        }
        
        public void houzhi(Object a) {
            System.out.println("后置通知"+a);
        }
        
        public void yichang(JoinPoint jp,Throwable ta) {
            System.out.println("异常通知");
            ta.printStackTrace();
        }
        
        public void zuizhong() {
            System.out.println("最终通知");
        }
        
        public void huanrao(ProceedingJoinPoint pjp) {
            try {
                System.out.println("环绕前");
                pjp.proceed();
                System.out.println("环绕后");
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                System.out.println("环绕异常");
                e.printStackTrace();
            }finally {
                System.out.println("环绕最终");
            }
        }
    }

    ApplicationContext.xml

     <!-- 切面1 -->
        <bean id="qieMian1" class="com.zy.spring.tools.aop.QieMian1"></bean> <!-- 创建一个切面的bean -->
        <aop:config> <!-- aop配置标签 -->
            <aop:pointcut expression="execution(* com.zy.spring.service.*.*(..))" id="pc1"/> <!-- 创建一个切点 -->
            <aop:aspect order="1"  ref="qieMian1"><!-- 创建一个切面   order是切面创建的顺序   ref链接上面创建的切面bean -->
                <aop:before method="qianzhi" pointcut-ref="pc1"/><!-- 前置通知 -->
                <aop:after-returning method="houzhi" pointcut-ref="pc1" returning="a"/> <!-- 后置通知   returning返回参数-->
                <aop:after-throwing method="yichang" pointcut-ref="pc1" throwing="ta"/> <!-- 异常通知   throwing返回参数-->
                <aop:after method="zuizhong" pointcut-ref="pc1"/> <!-- 最终通知 -->
                <aop:around method="huanrao" pointcut-ref="pc1"/> <!-- 环绕通知 -->
            </aop:aspect>
        </aop:config> 

    常用的@AspectJ形式Pointcut表达式的标志符:

    1、execution:
    Spring AOP仅支持方法执行类型的Joinpoint 所以execution将会是我们用的最多的标志符,用它来帮我们匹配拥有指定方法前面的Joinpoint。

    匹配方法execution

    execution(返回类型 类的路径.类名.函数名(参数类型1,参数类型2))

    execution(String com.chinasofti.Target.save(String))

    execution(* com.chinasofti.Target.save(String))

    execution(* com.chinasofti.*.save(String))

    execution(* com.chinasofti.*.*(String))

    execution(* com..*.*(..))


    2、Within:
    Within标志符只接受类型声明,它将匹配指定类型下所有的Joinpoint。

    匹配类within

    匹配到类
    <aop:pointcut id="targetPintcut" expression="within(com.chinasofti.Target)"/>
    调用这个类中的任何一个方法,都会走通知

    匹配到包下的类
    <aop:pointcut id="targetPintcut" expression="within(com.chinasofti.*)"/>
    调用这个包下的任何一个类中的方法,都会走通知

    匹配到包下及子包下的类
    <aop:pointcut id="targetPintcut" expression="within(com..*)"/>
    调用com这个包下的,所有子包及其一个类中的方法,都会走通知

    2.AOP通知(注解配置)

    QieMian2.java

    @Aspect//定义切面
    @Component//注册bean
    public class QieMian2 {
        @Pointcut("execution(* com.zy.spring.service.*.*(..))") //标记切点规则
        public void pointcut() {};//创建一个空的方法,相当于切入方法
        
        @Before("pointcut()") //前置通知  切点就是上面创建的pointcut()方法
        public void qianzhi(JoinPoint jp) {
            System.out.println("注解前置通知");
            Object [] os = jp.getArgs();
            for (Object object : os) {
                System.out.println("参数列表为:"+object);
            }
        }
        @AfterReturning(pointcut="pointcut()",returning="a")//后置通知  returning是方法中定义的参数
        public void houzhi(Object a) {
            System.out.println("注解后置通知"+a);
        }
        @AfterThrowing(pointcut="pointcut()",throwing="ta")//异常通知  throwing是方法中定义的参数
        public void yichang(JoinPoint jp,Throwable ta) {
            System.out.println("注解异常通知");
            ta.printStackTrace();
        }
        @After("pointcut()")//最终通知
        public void zuizhong() {
            System.out.println("注解最终通知");
        }
        @Around("pointcut()")//环绕通知
        public void huanrao(ProceedingJoinPoint pjp) {
            try {
                System.out.println("注解环绕前");
                pjp.proceed();//放行
                System.out.println("注解环绕后");
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                System.out.println("注解环绕异常");
                e.printStackTrace();
            }finally {
                System.out.println("注解环绕最终");
            }
        }
    }

    ApplicationContext.xml

           <!-- 注解扫描AOP -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    使用注解aop功能,加入aop1的注解扫描即可。

  • 相关阅读:
    Scala之eq,equals,==的区别
    Spark Streaming流计算特点及代码案例
    刷题50—水壶问题
    刷题49(力扣3道题)
    刷题48——最长回文串
    刷题47——矩形重叠
    刷题46——拼写单词
    刷题45(力扣两道题)
    刷题44——岛屿的最大面积
    刷题43——最长上升子序列
  • 原文地址:https://www.cnblogs.com/zhangyuan1024/p/12015130.html
Copyright © 2011-2022 走看看