• Spring AOP 切面编程的方法


    spring aop的使用分为两种,一种是使用注解来实现,一种是使用配置文件来实现。

    先来简单的介绍一下这两种方法的实现,接下来详细的介绍各处的知识点便于查阅。目录如下:

    1.基于注解实现spring aop

    2.基于配置文件实现spring aop

    3.增强的分类

    4.切点表达式的构成

    1.基于注解来实现的方法

    基于注解并不意味着不需要配置文件,只不过是在配置文件中所需要的配置很少。切面编程,显然我们需要一个增强类,一个被增强的普通类。

    配置文件中需要添加以下的内容

    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation=
    "http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"       <!--引入配置-->
    
    <context:component-scan base-package="com.test.aspect"/>         <!--扫描这两个包-->
    <context:component-scan base-package="com.test.user"/> 

    <aop:aspectj-autoproxy/> <!--开启aop自动扫描-->

    下面是增强类

    package com.test.aspect;

    @Component
    @Aspect
    public class TestAspect{
    @Before(
    "execution(* com.test.user.Login.greetTo(..))") public void beforeDoing(){ //do somthing } }

    下面是被增强类

    @Component
    public
    Class Login{ public void greetTo(){ //some action } }

    这样就可以完成对被增强类的增强。

    2.基于配置文件的方式

    非注解方式的首先把上面的注解都去掉,主要内容在配置文件中,配置文件如下       (其实还有  <aop:advisor>的配置,不过是旧版本所用,如果spring版本较低使用)

    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation=
    "http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"       <!--引入配置-->
    
    
    <aop:config proxy-target-class="true">         <!--aop config 是最外层的内容-->
          <aop:pointcut id="pc" expression="execution(* com.test.aspect.*(..))"/>     <!--首先定义了切入点-->     
          <aop:aspect ref="TestAspect" order="2">                                               <!--定义了增强类  order指的是增强织入的顺序-->   
                    <aop:before method="beforeDoing" pointcut-ref="pc"/>              <!--指定增强类中一个方法为before增强,切入点为之前定义的切入点-->
           </aop:aspect>
    </aop:config>

     3.增强的分类

    增强主要有以下几种:1.before  2.after 3.after-returning 4.after-throwing 5.around

    依次进行一下介绍,提供注解方式和配置文件方式

    // before 增强是在所需要增强的方法执行之前被织入
    
    @before("execution(* org.test.*.*(..))")
    public void beforeAction(JoinPoint jp)  //如果要使用joinpoint必须是第一个参数
    {
         jp.getSignature().getName();  //获得目标方法
         jp.getArgs(); //获得目标方法的参数
         //dosomething  
    }
    
    在配置文件中写成
    <aop:before pointcut="execution(* org.test.*.*(..))" method="beforeAction"/>
    //after 增强无论目标方法如何结束,都会织入在方法的后面
    
    @After("execution(* org.test.*.*(..))")
    public void afterAction(JoinPoint jp){
    
            //doSomething()
    
    }
    
    <aop :after pointcut="execution(* org.test.*.*(..))" method="afterAction">
    //AfterReturning 将在目标方法正常完成后被织入
    
    @AfterReturning(returning ="rvt" ,pointcut="execution(* org.test.*.*(..))")
    public void log(JointPoint jp,Object rvt){
        //rvt是目标方法的返回值
    }
    
    <aop:after-returning pointcut="execution(* org.test.*.*(..))" method="log"/>
    //afterthrowing 用于处理程序中未被处理的异常
    
    @AfterThrowing(throwing="ex",pointcut="execution(* org.test.*.*(..))")
    public void recovery(Throwable ex){
        
          //ex 是目标方法抛出的异常
    }
    
    <aop:after-throwing pointcut="execution(* org.test.*.*(..))" method="recovery" throwing="ex">
    //round 功能比较强大,可以环绕被增强方法
    
    @Around("execution(* org.test.*.*(..))")
    public Object round(ProceedingJoinPoint pjp){
         Object[] args=jp.getArgs(); //获得参数
         Object rvt=jp.procceed(args);//调用目标方法,可以将修改后的参数传入
         return rvt+1;   //可以对返回值进行处理
    }   
    
    <aop:around pointcut="execution(* org.test.*.*(..))" method="round"/>

    4.切点表达式的构成

    //可以定义一个切点,然后后续重复使用,比较方便
    
    @Pointcut("execution(* org.test.*.*(..))")
    public void myPointcut(){}
    
    
    @Before(pointcut="myPointcut")
    public void before(){
          ....
    }
    
    //下面是配置文件方法中的对应内容
    <aop:poincut id="myPointcut" expression=""execution(* org.test.*.*(..))""/>
    <aop:aspect ref="TestAspect">
    <aop:before method="before" pointcut-ref="myPointcut"/>

    </aop:aspect>

    之前所用的切点指示符只有 execution   还有 within this target  args  下面依次进行介绍

    execution(1? 2 3? 4(5) 6?)
    1.指定方法的修饰符 public private等,该部分可省略
    2.指定方法的返回值  该部分不可省略 不过一般用*代表任意返回值
    3.指定方法所属的类  可以省略,可用通配符
    4.指定方法名,可用通配符,不可省略
    5.指定方法的参数支持*与.. ()表示没有参数 (*)表示一个任意类型的参数 (..)表示任意数量的参数  (String,..)表示有一个String 参数,后面可以有任意个参数不可省略
    6.指定方法声明要抛出的异常(throws) 可用通配符 可省略
    
    eg.  execution(* org.test.service.impl.*.*(..))//org.test.service.imple 包下所有类的所有方法

    pointcut="execution
    (* org.test.service.impl.*.*(..))"
    //args 表示入参的类型 当入参类型匹配时织入 强调参数,可用execution代替
    arg(Integer)
    
    //within  类匹配模式
    within(org.test.User)     //匹配User中的所有类,最小粒度,不能到方法
    within(org.test.*)       //匹配org.test包中的所有类
    within(org.test..*)       //匹配org.test包及子孙包中的所有类
    
    //target和within类似,匹配符合的类别
    
    
    //this判断代理对象的类是否匹配
    
    //这几种都没怎么用过,所以简略提一下,用到后再补充

    切点表达式也可以用复合的方式 && || !  

    用法很简单,而且个人感觉用处并不大...

    @Before("A&&B")  AB均为之前描述的表达式  
    
    如果在xml中配置则要用and or等     pointcut="A and B"

    先写到这里,如果有需要补充的再来!

  • 相关阅读:
    PLAYBOOK 命令统计资源利用率 输出本地文件 flask展示
    如何对PFX证书转换成PEM格式证书
    Openshift学习
    Playbook handlers使用
    网络空间安全基础篇(2)----wireshark
    网络空间安全基础篇(1)----nmap的使用
    opencv——图像掩码操作
    opencv图像阈值操作
    在图片上绘制图形和添加文字
    使用opencv去操作树莓派摄像头保存图片和视频
  • 原文地址:https://www.cnblogs.com/mamuluke/p/5161747.html
Copyright © 2020-2023  润新知