Spring AOP Example – Advice

我们知道Spring有两个重要的特性:IOC和AOP ,大学期间只是对Spring有一个粗浅的认识,认为spring就是配置类,建立bean,然后就可以调用类的方法。直到慢慢了解才知道Spring还有很深的东西,Spring的强大。

        这篇博文主要讲述Spring AOP 的 hijack(拦截) 功能,主要描述为当我们在执行一个类的方法的时候我们可以在方法执行前和执行后增加额外的方法

        原文就是 Spring AOP can hijack the executing method,and add extra functionality before or after the method execution

     我们先声明一个实体类,CustomerService

[java]  view plain copy
  1. package com.kwe.bean;                                                                                                                                     /** 
  2.  * bean 
  3.  * @author rey.yang 
  4.  * 
  5.  */  
  6. public class CustomerService {  
  7.     private String name;  
  8.     private String url;  
  9.    
  10.     public void setName(String name) {  
  11.         this.name = name;  
  12.     }  
  13.     public void setUrl(String url) {  
  14.         this.url = url;  
  15.     }  
  16.     public void printName() {  
  17.         System.out.println("Customer name : " + this.name);  
  18.     }  
  19.     public void printURL() {  
  20.         System.out.println("Customer website : " + this.url);  
  21.     }  
  22.     public void printThrowException() {  
  23.         throw new IllegalArgumentException();  
  24.     }  
  25. }  
   项目的目录大致是这样的:

Spring AOP Example – Advice_第1张图片

   配置文件spring-customer.xml 放在src的根目录下:

[html]  view plain copy
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  5.     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
  6.       
  7.       
  8.       
  9.     <bean id="customerService" class="com.kwe.bean.CustomerService">  
  10.         <property name="name" value="yang yang">property>  
  11.         <property name="url" value="http://www.csdn.net">property>  
  12.     bean>  
  13. beans>  

          测试配置是否OK?

[java]  view plain copy
  1. public class App {  
  2.     public static void main(String[] args) {  
  3.         ApplicationContext appContext = new ClassPathXmlApplicationContext(  
  4.                 new String[] { "spring-customer.xml" });  
  5.    
  6.         CustomerService cust = (CustomerService) appContext.getBean("customerService");  
  7.    
  8.         System.out.println("*************************");  
  9.         cust.printName();  
  10.         System.out.println("*************************");  
  11.         cust.printURL();  
  12.         System.out.println("*************************");  
  13.         try {  
  14.             cust.printThrowException();  
  15.         } catch (Exception e) {  
  16.         }  
  17.     }  
  18. }  

         输出如下:

        

[java]  view plain copy
  1. *************************  
  2. Customer name : yang yang  
  3. *************************  
  4. Customer website : http://www.csdn.net  
  5. *************************  

        我们建立一个拦截类HijackBeforeMethod继承MethodBeforeAdvice

[java]  view plain copy
  1. public class HijackBeforeMethod implements MethodBeforeAdvice{  
  2.   
  3.     @Override  
  4.     public void before(Method method, Object[] args, Object target)  
  5.             throws Throwable {  
  6.         System.out.println("HijackBeforeMethod:Before method hijack");  
  7.     }         
  8. }     

       然后在spring-customer2.xml下配置:
[html]  view plain copy
  1. <bean id="customerService" class="com.kwe.bean.CustomerService">  
  2.     <property name="name" value="yang yang">property>  
  3.     <property name="url" value="http://www.csdn.net">property>  
  4. bean>  
  5.   
  6. <bean id="hijackBeforeMethod" class="com.kwe.hijack.HijackBeforeMethod">bean>  
  7.   
  8. <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">  
  9.       
  10.     <property name="target" ref="customerService">property>  
  11.       
  12.       
  13.     <property name="interceptorNames">  
  14.         <list>  
  15.             <value>hijackBeforeMethodvalue>  
  16.         list>  
  17.     property>  
  18. bean>  
         这里解释一下   代表要拦截的类是customerService

         hijackBeforeMethod代表基于customerService拦截类的是HijackBeforeMethod

        执行一下App(把配置文件改成spring-customer2.xml和相关bean),

        

[java]  view plain copy
  1. public class App2 {  
  2.     public static void main(String[] args) {  
  3.         ApplicationContext appContext = new ClassPathXmlApplicationContext(  
  4.                 new String[] { "spring-customer2.xml" });  
  5.    
  6.         CustomerService cust =   
  7.                                 (CustomerService) appContext.getBean("customerServiceProxy");  
  8.    
  9.         System.out.println("*************************");  
  10.         cust.printName();  
  11.         System.out.println("*************************");  
  12.         cust.printURL();  
  13.         System.out.println("*************************");  
  14.         try {  
  15.             cust.printThrowException();  
  16.         } catch (Exception e) {  
  17.         }  
  18.     }  
  19. }  

        输出为:

[java]  view plain copy
  1. *************************  
  2. HijackBeforeMethod:Before method hijack  
  3. Customer name : yang yang  
  4. *************************  
  5. HijackBeforeMethod:Before method hijack  
  6. Customer website : http://www.csdn.net  
  7. *************************  
  8. HijackBeforeMethod:Before method hijack  
        我们可以看到它在每个方法的前面都做了一个拦截。

        同理,我们想在实体类的方法完成之后再进行操作,则我们可以建立一个HijackAfterMethod实现AfterReturningAdvice类:

[java]  view plain copy
  1. public class HijackAfterMethod implements AfterReturningAdvice{  
  2.     @Override  
  3.     public void afterReturning(Object returnValue, Method method, Object[] args,  
  4.             Object target) throws Throwable {  
  5.         System.out.println("HijackAfterMethod: After method hijacked!");  
  6.     }  
  7. }  

        在配置文件中进行相关配置,略微改变一点即可:

[java]  view plain copy
  1. "customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">  
  2.       
  3.     "target" ref="customerService">  
  4.       
  5.       
  6.     "interceptorNames">  
  7.           
  8.             hijackAfterMethod  
  9.           
  10.       
  11.   
[java]  view plain copy
  1. public class App3 {  
  2.     public static void main(String[] args) {  
  3.         ApplicationContext appContext = new ClassPathXmlApplicationContext(  
  4.                 new String[] { "spring-customer3.xml" });  
  5.    
  6.         CustomerService cust =   
  7.                                 (CustomerService) appContext.getBean("customerServiceProxy");  
  8.    
  9.         System.out.println("*************************");  
  10.         cust.printName();  
  11.         System.out.println("*************************");  
  12.         cust.printURL();  
  13.         System.out.println("*************************");  
  14.         try {  
  15.             cust.printThrowException();  
  16.         } catch (Exception e) {  
  17.         }  
  18.     }  
  19. }  

        执行一下,得到:

[java]  view plain copy
  1. *************************  
  2. Customer name : yang yang  
  3. HijackAfterMethod: After method hijacked!  
  4. *************************  
  5. Customer website : http://www.baidu.com  
  6. HijackAfterMethod: After method hijacked!  
  7. *************************  
        
       另外我们想拦截捕获的异常,则可以建立一个HijackThrowException实现ThrowsAdvice接口

[java]  view plain copy
  1. public class HijackThrowException implements ThrowsAdvice{  
  2.     public void afterThrowing(IllegalArgumentException e) throws Throwable{  
  3.         System.out.println("HijackThrowException:Throw exception hijacked");  
  4.     }  
  5. }  

       配置文件如上,只修改关键字段名字即可,主类的方法也是一样,执行一下看到,在抛出异常的时候就对方法进行了拦截。

[java]  view plain copy
  1. *************************  
  2. Customer name : yang yang  
  3. *************************  
  4. Customer website : http://www.baidu.com  
  5. *************************  
  6. HijackThrowException:Throw exception hijacked  
  

        那么我们想对实体类方法执行前和执行后进行拦截,我们要怎么办? ,这个稍微要复杂些....

[java]  view plain copy
  1. /** 
  2.  * 集合了方法拦截前后和异常的拦截 
  3.  * @author rey.yang 
  4.  * 
  5.  */  
  6. public class HijackAroundMethod implements MethodInterceptor{  
  7.     @Override  
  8.     public Object invoke(MethodInvocation methodInvocation) throws Throwable {  
  9.         /** 
  10.          * 相当于反射获取方法的名称 
  11.          * 方法的参数 
  12.          */  
  13.         System.out.println("Method name:"+methodInvocation.getMethod().getName());  
  14.         System.out.println("Method arguments:"+Arrays.toString(methodInvocation.getArguments()));  
  15.         //same with MethodBeforeAdvice  
  16.         System.out.println("HijackAroundMethod:Before method hijacked!");  
  17.         try {  
  18.             //proceed to original method call  
  19.             Object result = methodInvocation.proceed();  
  20.             //same with AfterReturningAdvice  
  21.             System.out.println("HijackAroundMethod:Before after hijacked!");  
  22.             return result;  
  23.         } catch (IllegalArgumentException e) {  
  24.             //same with ThrowAdvice  
  25.             System.out.println("HijackArounMethod:Throw exception hijacked!");  
  26.             throw e;  
  27.         }  
  28.     }  
  29. }  

        


        配置文件如下:

[java]  view plain copy
  1.        "hijackAroundMethodBean" class="com.kwe.hijack.HijackAroundMethod">  
  2.   
  3. "customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">  
  4.       
  5.     "target" ref="customerService">  
  6.       
  7.       
  8.     "interceptorNames">  
  9.           
  10.             hijackAroundMethodBean  
  11.           
  12.       
  13.   

        执行一下得到

[java]  view plain copy
  1. *************************  
  2. Method name:printName  
  3. Method arguments:[]  
  4. HijackAroundMethod:Before method hijacked!  
  5. Customer name : yang yang  
  6. HijackAroundMethod:Before after hijacked!  
  7. *************************  
  8. Method name:printURL  
  9. Method arguments:[]  
  10. HijackAroundMethod:Before method hijacked!  
  11. Customer website : http://www.baidu.com  
  12. HijackAroundMethod:Before after hijacked!  
  13. *************************  
  14. Method name:printThrowException  
  15. Method arguments:[]  
  16. HijackAroundMethod:Before method hijacked!  
  17. HijackArounMethod:Throw exception hijacked!  

          在Spring AOP中,应该掌握三种配置方法:Advice,Poingcut,Advisor ,上面的例子是Advice方式进行对方法的拦截。我们可以根据相应的需求进行对应的实现。

          原文链接:http://www.mkyong.com/spring/spring-aop-examples-advice/


http://blog.csdn.net/pearyangyang/article/details/45053913

你可能感兴趣的:(Spring)