zoukankan      html  css  js  c++  java
  • spring中的AOP

    AOP:  面向切面编程

    配置文件的头信息

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    </beans>

    AOP的核心组件:

    切面(Aspect):切面是封装通用业务逻辑的组件,可以作用到其他组件上。

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

    通知(Advice):用于指定组件作用到目标组件的具体位置。

    AOP前置通知:在目标组件的方法执行前执行的程序。

    切入点程序:

    package model;
    public class Chengxu {
    public void talk(String str){
    System.out.println("str="+str);
    }
    }

    切面程序:

    package model;
    import org.aspectj.lang.JoinPoint;
    public class Charu {
    public void log(JoinPoint jp){
    System.out.println("日志的方法");
    System.out.println("获取目标函数参数方式:" +jp.getArgs()[0]);
     //得到切入点程序中方法的参数
    System.out.println("获取目标对象:" +jp.getTarget().getClass().getName());
    //得到切入点程的 包名.类名
    System.out.println("获取目标函数的java反射对象:" +jp.getSignature());
     // 得到切入点程的    返回类型   包名.类名.方法名()
    
    System.out.println("执行前置通知");
    }
    }

    Applicationcontext.xml省略文件头信息

    <!--切入点程序 -->
        <bean id="chengxu" class="model.Chengxu"></bean>
        <!--切面程序 -->
        <bean id="charu" class="model.Charu"></bean>
    
        <!-- AOP配置跟标签 -->
        <aop:config>
            <!-- 切入点配置:expression切入点表达式  
                  * model....不限返回类型,如果方法没返回值也得加*
                (*)方法里面是什么参数类型都可以,如果方法没有参数,不加这个* 
               -->
            <aop:pointcut expression="execution(* model.Chengxu.talk(*))" id="chengxuPointCut"/>
            
            <!-- 切面配置 -->
            <!-- aspect切面程序依赖于谁 -->
            <aop:aspect ref="charu"> 
            <!-- 前置通知 -->
            <!--切面程序的方法 切入点依赖于谁  (简单的说,把这个方法前置在哪个方法前面) -->
                <aop:before method="log" pointcut-ref="chengxuPointCut"/>
            </aop:aspect>
        </aop:config>

    AOP后置通知:在目标组件的方法正常执行并返回参数后执行的程序。 

    切入点程序:

    package model;
    public class Chengxu {
    //此方法也可以没有返回值
    public String talk(String str){
    System.out.println("str="+str);
      return "保存成功";
    }
    }

    切面程序:

    package model;
    import org.aspectj.lang.JoinPoint;
    public class Charu {
    public void log(JoinPoint jp,Object ret){
    //如果切入点方法没返回值,那么这个Object ret省略不写
    System.out.println("后置");
    System.out.println("obj为目标组件方法返回值:" +ret);
    }
    }

    Applicationcontext.xml

    <!--切入点程序 -->
        <bean id="chengxu" class="model.Chengxu"></bean>
        
        <!--切面程序 -->
        <bean id="charu2" class="model.Charu2"></bean>
        
        <!-- AOP配置跟标签 -->
        <aop:config>
            <!-- 切入点配置:expression切入点表达式   
         * model....不限返回类型  
        (*)方法里面是什么参数类型都可以,方法没有参数,那就不加这个* 
               -->
            <aop:pointcut expression="execution(* model.Chengxu.talk(*))" id="chengxuPointCut"/>
            
        <!-- 切面配置 -->
        <!-- aspect切面程序依赖于谁 -->
        <aop:aspect ref="charu2"> 
        <!-- 前置通知 -->
        <!--切面程序的方法 切入点依赖于谁  (简单的说,把这个方法前置在哪个方法前面) -->
          <aop:after-returning method="log2" pointcut-ref="chengxuPointCut"
                returning="ret"/>
          <!--如果切入点程序没有返回值那么returning 就可以不写 -->
        </aop:aspect>
    </aop:config>

    异常通知:在目标组件的方法抛出异常信息后执行的程序。

     注:当前置通知和后置通知发生异常时,这个异常通知是不执行的,只有当目标组件发生异常时才执行。

    切面程序:

    package model;
    import org.aspectj.lang.JoinPoint;
    public class Charu3 {
    public void log3(JoinPoint jp,Throwable t){
    System.out.println("异常通知");
    System.out.println("t为目标组件发生异常的信息:" +t);
    }
    }

    切入点程序:

    package model;
    public class Chengxu {
    //有返回值的方法
    public String talk(String str){
    System.out.println("str="+str);
    System.out.println(10/0);//发生异常的地方
    return "保存成功";
    }
    }

    Application.xml

    <!--切入点程序 -->
        <bean id="chengxu" class="model.Chengxu"></bean>
        <!--切面程序 前置-->
        <bean id="charu" class="model.Charu"></bean>
        <!--切面程序2 后置-->
        <bean id="charu2" class="model.Charu2"></bean>
        <!--切面程序3 异常-->
        <bean id="charu3" class="model.Charu3"></bean>
        
        <!-- AOP配置跟标签 -->
        <aop:config>
            <!-- 切入点配置:expression切入点表达式   * model....不限返回类型  (*)方法里面是什么参数类型都可以,方法没有参数也可以那就不加这个* 
               -->
            <aop:pointcut expression="execution(* model.Chengxu.talk(*))" id="chengxuPointCut"/>
            
            <!-- 切面配置 -->
            <!-- aspect切面程序依赖于谁 -->
            <aop:aspect ref="charu"> 
                <!-- 前置通知 -->
                <!--切面程序的方法 切入点依赖于谁  (简单的说,把这个方法前置在哪个方法前面) -->
                <aop:before method="log" pointcut-ref="chengxuPointCut"/>
            </aop:aspect>
            
            
            <aop:aspect ref="charu2"> 
                <!-- 前置通知 -->
                <!--切面程序的方法 切入点依赖于谁  (简单的说,把这个方法前置在哪个方法前面) -->
                <aop:after-returning method="log2" pointcut-ref="chengxuPointCut"
                returning="ret"/>
            </aop:aspect>
            
            <aop:aspect ref="charu3"> 
            <!-- 异常通知 -->  
                <aop:after-throwing method="log3" pointcut-ref="chengxuPointCut"
                throwing="t"/>
            </aop:aspect>     
        </aop:config>

    最终通知:在目标组件的方法正常执行后执行,或在异常通知之前执行。

     注:也就是当目标组件发生没发生异常,都会被执行。

         如果目标组件异常时,那后置通知不会执行,异常通知会执行。最终通知会在异常通知之前执行。

         如果目标组件正常时,那最终通知会在后置通知之前执行。

    Application.xml

    <!-- 最终通知 -->
            <aop:after method="log4" pointcut-ref="chengxuPointCut"/>
            </aop:aspect>

    环绕通知:  切面程序负责调用目标组件的运行,与struts中的拦截器功能类似,可以完全取代之前的几个通知。

    切面程序:在类型为环绕通知的切面程序函数中,参数为org.aspectj.lang.ProceedingJoinPointJoinPoint的子类,扩展了JoinPoint类,提供了proceed()函数,该函数的作用是调用目标组件,并返回目标组件返回的值

    Application.xml

    <aop:aspect ref="charu5"> 
                <!-- 环绕通知 -->
                <aop:around method="log5" pointcut-ref="chengxuPointCut"/>
    </aop:aspect>

    切面程序:

    public class Charu5 {
        
        public void log5(ProceedingJoinPoint pjp) {
            System.out.println("前置通知");
            try {
                Object ob = pjp.proceed();//调用目标组件
                System.out.println("目标函数的返回值:"+ob);
                System.out.println("后置通知");
            } catch (Throwable e) {
                System.out.println("异常通知");
            }
            System.out.println("最终通知");
        }
        
    
    }

    注释方式实现以上内容

    XML中增加

    <context:component-scan base-package="com.china.model"></context:component-scan>

    <aop:aspectj-autoproxy ></aop:aspectj-autoproxy>

    @Aspect:代表切面程序

    在切面类下添加下面代码实现各自的功能

    前置通知:@Before(value="execution(* com.china.model.Chengxu.talk(*))")

    后置通知:@AfterReturning(value="execution(*com.china.model.Chengxu.talk(*))",returning="ret")

    异常通知:@AfterThrowing(value="execution(* com.china.model.Chengxu.talk(*))", throwing="e")

    最终通知:@After(value="execution(* com.china.model.Chengxu.talk(*))")

    环绕通知:@Around(value="execution(* com.china.model.Chengxu.talk(*))")

  • 相关阅读:
    VS调试问题整理 :无法在Web服务器上启动调试。您不具备调试此应用程序的权限...
    WebService参考 :什么是Web Services?(AMT研究院 袁磊)
    .NET和J2EE该相互学习什么?(转)
    使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码 (实例)
    C#参考 :ReferenceEquals, == , Equals
    使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码(详解)
    HTML参考 :TBODY元素 详解
    Indigo参考 (2) DataContract 使用 详解(转)
    Indigo参考 (1) :第一个Indigo Service (转)
    控件用法参考:DataList和Repeater控件的分页显示功能
  • 原文地址:https://www.cnblogs.com/lm970585581/p/7265766.html
Copyright © 2011-2022 走看看