4.3基于Schema的AOP

在Spring配置文件中,所以AOP相关定义必须放在<aop:config>标签下,该标签下可以有
<aop:pointcut>、<aop:advisor>、<aop:aspect>标签,配置顺序不可变。
<aop:pointcut>:用来定义切入点,该切入点可以重用;
<aop:advisor>:用来定义只有一个通知和一个切入点的切面;
<aop:aspect>:用来定义切面,该切面可以包含多个切入点和通知,而且标签内部的通知和切入点定义是无序的;和advisor的区别就在此,advisor只包含一个通知和一个切入点。

在这里插入图片描述

1 声明切面
 切面使用<aop:aspect>标签指定,ref属性用来引用切面支持Bean。
 切面支持Bean“aspectSupportBean”跟普通Bean完全一样使用,切面使用“ref”属性引用它。
2 声明切入点
切入点在Spring中也是一个Bean,Bean定义方式可以有三种方式:
    1)在<aop:config>标签下使用<aop:pointcut>声明一个切入点Bean,该切入点可以被多个切面使用,
    对于需要共享使用的切入点最好使用该方式,该切入点使用id属性指定Bean名字,
    在通知定义时使用pointcut-ref属性通过该id引用切入点,expression属性指定切入点表达式
<bean id="logAspect" class="com.yang.learn.aop.LogUtilAspect"></bean>
<aop:config>  
 <aop:pointcut id="pointcut" expression="execution(* com.yang.learn..*.*(..))"/>  
 <aop:aspect ref="logAspect">  
    <aop:before pointcut-ref="pointcut" method="before"/>  
 </aop:aspect>  
</aop:config>  
3 声明通知

基于Schema方式支持前边介绍的5中通知类型:

1.前置通知:在切入点选择的方法之前执行,
通过<aop:aspect>标签下的<aop:before>标签声明:
<aop:before pointcut="切入点表达式"  pointcut-ref="切入点Bean引用"  
method="前置通知实现方法名"  
arg-names="前置通知实现方法参数列表参数名字"/>  
 //前置通知切面
 public void beforeAdvice(String param) {
        System.out.println("===========before advice param:" + param);
    }
 //前置通知切入点
 public void putParam(String param){
    System.out.println("param is : " + param);
 }
<bean id="logAspect" class="com.yang.learn.aop.LogUtilAspect"></bean>
   <aop:config>
      <aop:pointcut id="pointCut2" expression="execution(* com.yang.learn..*.*(..)) and args(param)"></aop:pointcut>
       <aop:aspect ref="logAspect">
             <aop:before pointcut-ref="pointCut2" method="beforeAdvice" arg-names="param"></aop:before>
       </aop:aspect>
   </aop:config>
pointcut和pointcut-ref:二者选一,指定切入点;
method:指定前置通知实现方法名,如果是多态需要加上参数类型,多个用“,”隔开,如beforeAdvice(java.lang.String);
arg-names:指定通知实现方法的参数名字,多个用“,”分隔,在class文件中没生成变量调试信息是获取不到方法参数名字的,
因此只有在类没生成变量调试信息时才需要使用arg-names属性来指定参数名,如arg-names="param"表示通知实现方法的参数列表的第一个参数名字为“param”。
分析
1)切入点匹配:在配置中使用“execution(* cn.javass..*.sayBefore(..)) ”匹配目标方法sayBefore,且使用“args(param)”匹配目标方法只有一个参数且传入的参数类型为通知实现方法中同名的参数类型;
2)目标方法定义:使用method=" beforeAdvice(java.lang.String) "指定前置通知实现方法,且该通知有一个参数类型为java.lang.String参数;
3)目标方法参数命名:其中使用arg-names=" param "指定通知实现方法参数名为“param”,切入点中使用“args(param)”匹配的目标方法参数将自动传递给通知实现方法同名参数。
2.后置返回通知:在切入点选择的方法正常返回时执行,
通过<aop:aspect>标签下的<aop:after-returning>标签声明:
<aop:after-returning pointcut="切入点表达式"  pointcut-ref="切入点Bean引用"  
    method="后置返回通知实现方法名"  
    arg-names="后置返回通知实现方法参数列表参数名字"  
    returning="返回值对应的后置返回通知实现方法参数名"  
/>  
    //后置返回通知切面方法
    public void afterReturningAdvice(Object returnVal) {
        System.out.println("===========after returning Advice param:" + returnVal);
    }
	//后置通知切入点
    public boolean afterReturning(){
        System.out.println("executing after Retruning " );
        return true;
    }
<bean id="logAspect" class="com.yang.learn.aop.LogUtilAspect"></bean>
    <aop:config>
        <aop:pointcut id="pointCut3" expression="execution(* com.yang.learn..*.*(..))"></aop:pointcut>
        <aop:aspect ref="logAspect">
            <aop:after-returning pointcut-ref="pointCut3" method="afterReturningAdvice" returning="returnVal"></aop:after-returning>
        </aop:aspect>
    </aop:config>
  pointcut和pointcut-ref:同前置通知同义;
  method:同前置通知同义;
  arg-names:同前置通知同义;
  returning:定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法执行正常返回后,
 将把目标方法返回值传给通知方法;returning限定了只有目标方法返回值匹配与通知方法相应参数类型时才能执行后置返回通知,
 否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值。

分析

1)切入点匹配:在配置中使用“execution(* cn.javass..*.sayAfterReturning(..)) ”匹配目标方法sayAfterReturning,该方法返回true;
2)目标方法定义:使用method="afterReturningAdvice"指定后置返回通知实现方法;
3)目标方法参数命名:其中使用arg-names="retVal"指定通知实现方法参数名为“retVal”;
4)返回值命名:returning="retVal"用于将目标返回值赋值给通知实现方法参数名为“retVal”的参数上。

后置最终通知,后置异常通知跟上述基本一致

Advisor的使用

Advisor表示只有一个通知和一个切入点的切面,由于Spring AOP都是基于AOP联盟的拦截器模型的环绕通知的,所以引入Advisor来支持各种通知类型(如前置通知等5种),Advisor概念来自于Spring1.2对AOP的支持,在AspectJ中没有相应的概念对应。

Advisor可以使用<aop:config>标签下的<aop:advisor>标签定义
<aop:advisor pointcut="切入点表达式" pointcut-ref="切入点Bean引用"  
                     advice-ref="通知API实现引用"/>  
pointcut和pointcut-ref:二者选一,指定切入点表达式;
advice-ref:引用通知API实现Bean,如前置通知接口为MethodBeforeAdvice;

1.通知方法定义

public class BeforeAdvice implements MethodBeforeAdvice {

    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("before advice by advisor");
    }
}

2.定义Advisor

 <!-- 引入通知Bean -->
 <bean id="beforeAdvice" class="com.yang.learn.aop.advisor.BeforeAdvice"></bean>
 <!-- 配置切面 -->
 <aop:config>
     <aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointCut"></aop:advisor>
 </aop:config>

其他类型的Advisor通知,跟示例中的原理一样,可以自己试验
不推荐使用Advisor,除了在进行事务控制的情况下,其他情况一般不推荐使用该方式,该方式属于侵入式设计,必须实现通知API

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值