Spring AOP四种创建通知(拦截器)类型实例

系统 1826 0

1、Spring只支持方法拦截,也就是说,只能在方法的前后进行拦截,而不能在属性前后进行拦截。
2、Spring支持四种拦截类型:目标方法调用前(before),目标方法调用后(after),目标方法调用前后(around),以及目标方法抛出异常(throw)。
3、前置拦截的类必须实现MethodBeforeAdvice接口,实现其中的before方法。
4、后置拦截的类必须实现AfterReturningAdvice接口,实现其中的afterReturning方法。
5、前后拦截的类必须实现MethodInterceptor接口,实现其中的invoke方法。前后拦截是唯一可以控制目标方法是否被真正调用的拦截类型,也可以控制返回对象。而前置拦截或后置拦截不能控制,它们不能印象目标方法的调用和返回。
但是以上的拦截的问题在于,不能对于特定方法进行拦截,而只能对某个类的全部方法作拦截。所以下面引入了两个新概念:“切入点”和“引入通知”。
6、”切入点“的定义相当于更加细化地规定了哪些方法被哪些拦截器所拦截,而并非所有的方法都被所有的拦截器所拦截。在ProxyFactoryBean的属性中,interceptorNames属性的对象也由拦截(Advice)变成了引入通知(Advisor),正是在Advisor中详细定义了切入点(PointCut)和拦截(Advice)的对应关系,比如常见的基于名字的切入点匹配(NameMatchMethodPointcutAdvisor类)和基于正则表达式的切入点匹配(RegExpPointcutAdvisor类)。这些切入点都属于”静态切入点“,因为他们只在代理创建的时候被创建一次,而不是每次运行都创建。

 

下面我们进行实例的开发

 

首先创建业务接口:

 

package  AdvisorTest;

public   interface  Shopping  ... {
  
public  String buySomething(String type);
  
public  String buyAnything(String type);
  
public   void  testException();
}

 下面是业务实现类,我们的通知就是以这些实现类作为切面,在业务方法前后加入我们的通知代码

 

package  AdvisorTest;

public   class  ShoppingImpl  implements  Shopping  ... {
    
private  Customer customer;
    
public  Customer getCustomer()  ... {
        
return  customer;
    }

    
public   void  setCustomer(Customer customer)  ... {
        
this .customer  =  customer;
    }

    
public  String buySomething(String type)  ... {
        System.out.println(
this .getCustomer().getName() + "  bye  " + type + "  success " );
        
return   null ;
    }

    
    
public  String buyAnything(String type)  ... {
       System.out.println(
this .getCustomer().getName() + "  bye  " + type + "  success " );
       
return   null ;

     }

    
public   void  testException() ... {
        
throw   new  ClassCastException();
    }

}

 

(1)前置通知

        配置了前置通知的bean,在执行业务方法前,均会执行前置拦截器的before方法

package  AdvisorTest;

import  java.lang.reflect.Method;

import  org.springframework.aop.MethodBeforeAdvice;
// 前置通知
public   class  WelcomeAdvice  implements  MethodBeforeAdvice  ... {

    
public   void  before(Method method, Object[] args, Object obj)
            
throws  Throwable  ... {
        String type
= (String)args[ 0 ];
        System.out.println(
" Hello welcome to bye  " + type);

    }


}

 

(2)后置通知

配置了前置通知的bean,在执行业务方法前,均会执行前置拦截器的afterReturnning方法

 

package  AdvisorTest;

import  java.lang.reflect.Method;

import  org.springframework.aop.AfterReturningAdvice;
import  org.springframework.aop.MethodBeforeAdvice;
// 后置通知
public   class  ThankYouAdvice  implements  AfterReturningAdvice  ... {

    
public   void  afterReturning(Object obj, Method method, Object[] arg1,
            Object arg2) 
throws  Throwable  ... {
        
         String type
= (String)arg1[ 0 ];
         System.out.println(
" Hello Thankyou to bye  " + type);
    }

    

}

 

(3)环绕通知

配置了前置通知的bean,在执行业务方法前后,均会执行前置拦截器的invoke方法

需要注意的是必须调用目标方法,如不调用,目标方法将不被执行

package  AdvisorTest;

import  org.aopalliance.intercept.MethodInterceptor;
import  org.aopalliance.intercept.MethodInvocation;

public   class  MethodAdvisor  implements  MethodInterceptor  ... {

    
public  Object invoke(MethodInvocation invocation)  throws  Throwable  ... {
        String str
= (String)invocation.getArguments()[ 0 ];
        System.out.println(
" this is before " + str + "  in MethodInterceptor " );
        Object obj
= invocation.proceed();  // 调用目标方法,如不调用,目标方法将不被执行
        System.out.println( " this is after " + str + "  in MethodInterceptor " );
        
return   null ;
    }


}

 

(4)异常通知

ThrowsAdvice是一个标示接口,我们可以在类中定义一个或多个,来捕获定义异常通知的 bean抛出的异常,并在抛出异常前执行相应的方法

public void afterThrowing(Throwable throwa){}

或者

public void afterThrowing(Method method,Object[] args,Object target,Throwable throwable){

package  AdvisorTest;

import  org.springframework.aop.ThrowsAdvice;

public    class  ExceptionAdvisor  implements  ThrowsAdvice  ... {
  
public   void  afterThrowing(ClassCastException e) ... {
      System.out.println(
" this is from exceptionAdvisor " );
  }

}

 

配置文件

 

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"  >
< beans >
 
< bean  id ="customer"  class ="AdvisorTest.Customer" >
   
< constructor-arg  index ="0" >
     
< value > gaoxiang </ value >
   
</ constructor-arg >
    
< constructor-arg  index ="1" >
     
< value > 26 </ value >
   
</ constructor-arg >
 
</ bean >
 
 
< bean  id ="shoppingImpl"  class ="AdvisorTest.ShoppingImpl" >
   
< property  name ="customer" >
     
< ref  local ="customer" />
   
</ property >
 
</ bean >

<!--  前置通知  -->
< bean  id ="welcomeAdvice"  class ="AdvisorTest.WelcomeAdvice" />
< bean  id ="welcomeAdviceShop"  class ="org.springframework.aop.framework.ProxyFactoryBean" >
  
< property  name ="proxyInterfaces" >
    
< value > AdvisorTest.Shopping </ value >
  
</ property >
  
< property  name ="target" >
    
< ref  local ="shoppingImpl" />
  
</ property >
  
< property  name ="interceptorNames" >
    
< list >
      
< value > welcomeAdvice </ value >
    
</ list >
  
</ property >
  
</ bean >

<!--  后置通知  -->
< bean  id ="thankyouAdvice"  class ="AdvisorTest.ThankYouAdvice" />
< bean  id ="thankyouAdviceShop"  class ="org.springframework.aop.framework.ProxyFactoryBean" >
  
< property  name ="proxyInterfaces" >
    
< value > AdvisorTest.Shopping </ value >
  
</ property >
  
< property  name ="target" >
    
< ref  local ="shoppingImpl" />
  
</ property >
  
< property  name ="interceptorNames" >
    
< list >
      
< value > thankyouAdvice </ value >
    
</ list >
  
</ property >
  
</ bean >

<!--  环绕通知  -->
< bean  id ="methodAdvice"  class ="AdvisorTest.MethodAdvisor" />
< bean  id ="methodAdviceShop"  class ="org.springframework.aop.framework.ProxyFactoryBean" >
  
< property  name ="proxyInterfaces" >
    
< value > AdvisorTest.Shopping </ value >
  
</ property >
  
< property  name ="target" >
    
< ref  local ="shoppingImpl" />
  
</ property >
  
< property  name ="interceptorNames" >
    
< list >
  &nb

Spring AOP四种创建通知(拦截器)类型实例


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论