代理模式,JDK动态代理,SpringAOP来龙去脉

来源:互联网 发布:太原医院挂号软件 编辑:程序博客网 时间:2024/05/01 17:39
这里我们学习一下代理模式,JDK的动态代理,以及以JDK为基础的springAOP实现 
代理模式:类结构的模式,优点就是不需要更改原有类(被代理类)就能增强原有类(被代理类)的功能,缺点就是必须实现原有类(被代理类)的接口 
JDK的动态代理:优点就是不必“复制”原有类(被代理类)接口实现类,缺点就是必须为每个被代理类实现几乎一样的方法 
springAOP:优点就是采用springIOC,JDK动态代理等技术来实现AOP机制 
我们展示一个类的几个方法,分别采用代理模式,JDK动态代理,springAOP机制来做些额外功能 
这里定义一个接口,一个实现类 
Java代码  收藏代码
  1. package com.fruitking.proxy;  
  2.   
  3. /** 
  4.  * 汽车服务类接口 
  5.  * @author fruitking 
  6.  * @since 2010-02-23 
  7.  */  
  8. public interface CarService {  
  9.       
  10.     /** 
  11.      * 启动汽车 
  12.      */  
  13.     public void start();  
  14.       
  15.     /** 
  16.      * 获得汽车搭载人数 
  17.      * @return 
  18.      */  
  19.     public int getLoadAmount();  
  20.       
  21.     /** 
  22.      * 设置驾驶员 
  23.      * @param driver 
  24.      * @return 
  25.      */  
  26.     public String setDriver(String driver);  
  27.       
  28.     /** 
  29.      * 搭载货物 
  30.      * @param goods 
  31.      * @throws NullPointerException 
  32.      * @throws IllegalArgumentException 
  33.      */  
  34.     public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException;  
  35. }  


Java代码  收藏代码
  1. package com.fruitking.proxy;  
  2.   
  3. /** 
  4.  * 汽车服务类接口实现 
  5.  * @author fruitking 
  6.  * @since 2010-02-23 
  7.  */  
  8. public class CarServiceImpl implements CarService{  
  9.       
  10.     /** 
  11.      * 启动汽车 
  12.      */  
  13.     public void start(){  
  14.         System.out.println("start my car...");  
  15.     }  
  16.       
  17.     /** 
  18.      * 获得汽车搭载人数 
  19.      * @return 
  20.      */  
  21.     public int getLoadAmount(){  
  22.         System.out.println("count the person amount in my car...");  
  23.         return 5;  
  24.     }  
  25.       
  26.     /** 
  27.      * 设置驾驶员 
  28.      * @param driver 
  29.      * @return 
  30.      */  
  31.     public String setDriver(String driver){  
  32.         System.out.println("driver is:"+driver);  
  33.         if(driver==null||"".equals(driver)){  
  34.             return "There is not driver.";  
  35.         }else{  
  36.             return "The driver's name is " + driver + ".";  
  37.         }  
  38.     }  
  39.       
  40.     /** 
  41.      * 搭载货物 
  42.      * @param goods 
  43.      * @throws NullPointerException 
  44.      * @throws IllegalArgumentException 
  45.      */  
  46.     public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{  
  47.         if(goods==null||"".equals(goods)){  
  48.             throw new NullPointerException("The argument goods is null.");  
  49.         }else if("tiger".equals(goods)){  
  50.             throw new IllegalArgumentException("The argument goods is invalid.");  
  51.         }  
  52.         System.out.println("load goods is:"+goods);  
  53.     }  
  54. }  

先来看看代理模式,定义一个代理类,然后调用代理类 
Java代码  收藏代码
  1. package com.fruitking.proxy.pattern;  
  2.   
  3. import com.fruitking.proxy.CarService;  
  4.   
  5. /** 
  6.  * 汽车服务类接口的代理类实现 
  7.  * @author fruitking 
  8.  * @since 2010-02-23 
  9.  */  
  10. public class CarServiceProxy implements CarService {  
  11.       
  12.     private CarService carServiceTarget;//被代理的目标类  
  13.       
  14.     /** 
  15.      * 在构造函数中设置被代理的目标类 
  16.      * 也可以使用set方法设置被代理的目标类 
  17.      * @param carServiceTarget 
  18.      */  
  19.     public CarServiceProxy(CarService carServiceTarget){  
  20.         this.carServiceTarget = carServiceTarget;  
  21.     }  
  22.   
  23.     /** 
  24.      * 启动汽车 
  25.      */  
  26.     public void start(){  
  27.         System.out.println("before excute target object...");  
  28.         carServiceTarget.start();  
  29.         System.out.println("after excute target object...");  
  30.     }  
  31.       
  32.     /** 
  33.      * 获得汽车搭载人数 
  34.      * @return 
  35.      */  
  36.     public int getLoadAmount(){  
  37.         System.out.println("before excute target object...");  
  38.         int amount = carServiceTarget.getLoadAmount();  
  39.         System.out.println("after excute target object...");  
  40.         return amount;  
  41.     }  
  42.       
  43.     /** 
  44.      * 设置驾驶员 
  45.      * @param driver 
  46.      * @return 
  47.      */  
  48.     public String setDriver(String driver){  
  49.         System.out.println("before excute target object...");  
  50.         String resultObject = carServiceTarget.setDriver(driver);  
  51.         System.out.println("after excute target object...");  
  52.         return resultObject;  
  53.     }  
  54.       
  55.     /** 
  56.      * 搭载货物 
  57.      * @param goods 
  58.      * @throws NullPointerException 
  59.      * @throws IllegalArgumentException 
  60.      */  
  61.     public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{  
  62.         //这里不实现任何操作  
  63.     }  
  64. }  


Java代码  收藏代码
  1. package com.fruitking.proxy.pattern;  
  2.   
  3. import com.fruitking.proxy.CarService;  
  4. import com.fruitking.proxy.CarServiceImpl;  
  5.   
  6. public class TestProxyPattern {  
  7.   
  8.     /** 
  9.      * 代理模式中的调用 
  10.      * @param args 
  11.      */  
  12.     public static void main(String[] args) {  
  13.         CarService carServiceTarget = new CarServiceImpl();  
  14.         CarServiceProxy carServiceProxy = new CarServiceProxy(carServiceTarget);  
  15.         //执行代理类的方法  
  16.         //作用一:间接执行被代理类的方法,  
  17.         //作用二:代理类可以在被代理类方法执行前后做一些额外操作  
  18.         //总结:不更改原有类的功能和程序代码情况下,实现额外的功能能  
  19.         //缺点:要为每个被代理类编写一个代理类,且需要实现相同接口的所有方法  
  20.         carServiceProxy.start();  
  21.         carServiceProxy.getLoadAmount();  
  22.         String driver = carServiceProxy.setDriver("fruitking");  
  23.         System.out.println(driver);  
  24.     }  
  25. }  


再来看看JDK动态代理 
Java代码  收藏代码
  1. package com.fruitking.proxy.jdkdproxy;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5.   
  6. import com.fruitking.proxy.CarService;  
  7.   
  8. /** 
  9.  * java动态代理实现类 
  10.  * @author fruitking 
  11.  * @since 2010-02-23 
  12.  */  
  13. public class CarServiceJDKDynamicProxy implements InvocationHandler {  
  14.   
  15.     private CarService carServiceTarget;//被代理的目标类  
  16.       
  17.     /** 
  18.      * 在构造函数中设置被代理的目标类 
  19.      * 也可以使用set方法设置被代理的目标类 
  20.      * @param carServiceTarget 
  21.      */  
  22.     public CarServiceJDKDynamicProxy(CarService carServiceTarget){  
  23.         this.carServiceTarget = carServiceTarget;  
  24.     }  
  25.       
  26.     public Object invoke(Object proxy, Method method, Object[] args)  
  27.             throws Throwable {  
  28.         System.out.println("before excute target object...");  
  29.         Object object = method.invoke(this.carServiceTarget,args);  
  30.         System.out.println("after excute target object...");  
  31.         return object;  
  32.     }  
  33. }  


Java代码  收藏代码
  1. package com.fruitking.proxy.jdkdproxy;  
  2.   
  3. import java.lang.reflect.Proxy;  
  4.   
  5. import com.fruitking.proxy.CarService;  
  6. import com.fruitking.proxy.CarServiceImpl;  
  7.   
  8. public class TestJDKDynamicProxy {  
  9.   
  10.     /** 
  11.      * JDK中动态代理技术中的代理调用 
  12.      * @param args 
  13.      */  
  14.     public static void main(String[] args) {  
  15.         CarService carServiceTarget = new CarServiceImpl();  
  16.         CarServiceJDKDynamicProxy carServiceJDKDynamicProxyTarget = new CarServiceJDKDynamicProxy(carServiceTarget);  
  17.         CarService carServiceProxy = (CarService)Proxy.newProxyInstance(carServiceTarget.getClass().getClassLoader(),new Class[]{CarService.class}, carServiceJDKDynamicProxyTarget);  
  18.         //执行代理类的方法  
  19.         //作用一:间接执行被代理类的方法,  
  20.         //作用二:代理类可以在被代理类方法执行前后做一些额外操作  
  21.         //总结:不更改原有类的功能和程序代码情况下,实现额外的功能能  
  22.         //缺点:要为每个被代理类编写一个代理类,且具有相同的接口  
  23.         carServiceProxy.start();  
  24.         carServiceProxy.getLoadAmount();  
  25.         String driver = carServiceProxy.setDriver("fruitking");  
  26.         System.out.println(driver);  
  27.     }  
  28.   
  29. }  


最后来看看spring的AOP机制的实现 
Java代码  收藏代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import org.springframework.aop.MethodBeforeAdvice;  
  6.   
  7. /** 
  8.  * 使用spring的AOP机制的事前通知接口实现 
  9.  * @author fruitking 
  10.  * @since 2010-02-23 
  11.  */  
  12. public class CarServiceBeforeAdvice implements MethodBeforeAdvice{  
  13.       
  14.     public void before(Method method, Object[] args, Object target)throws Throwable {  
  15.         System.out.println("before excute target object...");  
  16.         String methodName = method.getName();  //得到方法名   
  17.         String targetClassName = target.getClass().getName();//得到调用类名  
  18.         System.out.println(targetClassName+"."+methodName+"()");  
  19.     }  
  20. }  

Java代码  收藏代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import org.springframework.aop.AfterReturningAdvice;  
  6.   
  7. /** 
  8.  * 使用spring的AOP机制的事前通知接口实现 
  9.  * @author fruitking 
  10.  * @since 2010-02-23 
  11.  */  
  12. public class CarServiceAfterAdvice implements AfterReturningAdvice {  
  13.   
  14.     public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable{  
  15.         String methodName = method.getName();  //得到方法名   
  16.         String targetClassName = target.getClass().getName();//得到调用类名  
  17.         System.out.println(targetClassName+"."+methodName+"()");  
  18.         System.out.println("after excute target object...");  
  19.     }  
  20. }  

Java代码  收藏代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import org.aopalliance.intercept.MethodInterceptor;  
  4. import org.aopalliance.intercept.MethodInvocation;  
  5.   
  6. /** 
  7.  * 使用spring的AOP机制的事前通知接口实现 
  8.  * @author fruitking 
  9.  * @since 2010-02-23 
  10.  */  
  11. public class CarServiceAroundAdvice implements MethodInterceptor {  
  12.       
  13.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  14.         System.out.println("before around excute target object...");  
  15.         String methodName = invocation.getMethod().getName();  //得到方法名   
  16.         String targetClassName = invocation.getClass().getName();//得到调用类名  
  17.         System.out.println(targetClassName+"."+methodName+"()");  
  18.         Object result = invocation.proceed(); //调用横切点,即真实操作  
  19.         System.out.println("after around excute target object...");  
  20.         return result;  
  21.     }  
  22. }  

Java代码  收藏代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import org.springframework.aop.ThrowsAdvice;  
  4.   
  5. /** 
  6.  * 使用spring的AOP机制的事前通知接口实现 
  7.  * @author fruitking 
  8.  * @since 2010-02-23 
  9.  */  
  10. public class CarServiceThrowsAdvice implements ThrowsAdvice {  
  11.       
  12.     public void afterThrowing(NullPointerException e){//可以定义多个方法,只要传入的参数是不同异常  
  13.         System.out.print("not load anything goods!");  
  14.     }  
  15.       
  16.     public void afterThrowing(IllegalArgumentException e){//可以定义多个方法,只要传入的参数是不同异常  
  17.         System.out.print("load a tiger,it's very much dangerous!");  
  18.     }  
  19.   
  20. }  

spring的配置文件,把这些使用IOC处理 
Java代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">  
  3. <beans>  
  4.       
  5.     <bean id="carServiceTarget" class="com.fruitking.proxy.CarServiceImpl"/>  
  6.        
  7.     <bean id="carServiceBeforeAdvice" class="com.fruitking.proxy.springaop.CarServiceBeforeAdvice"/>  
  8.       
  9.     <bean id="carServiceAfterAdvice" class="com.fruitking.proxy.springaop.CarServiceAfterAdvice"/>  
  10.       
  11.     <bean id="carServiceAroundAdvice" class="com.fruitking.proxy.springaop.CarServiceAroundAdvice"/>  
  12.       
  13.     <bean id="carServiceThrowsAdvice" class="com.fruitking.proxy.springaop.CarServiceThrowsAdvice"/>  
  14.       
  15.     <bean id="carService" class="org.springframework.aop.framework.ProxyFactoryBean">   
  16.         <property name="proxyInterfaces" value="com.fruitking.proxy.CarService"/>   
  17.         <property name="target" ref="carServiceTarget"/>   
  18.         <property name="interceptorNames">   
  19.             <list>   
  20.                 <value>carServiceBeforeAdvice</value>  
  21.                 <value>carServiceAfterAdvice</value>  
  22.                 <value>carServiceAroundAdvice</value>  
  23.                 <value>carServiceThrowsAdvice</value>  
  24.             </list>   
  25.         </property>  
  26.     </bean>  
  27.       
  28. </beans>  

Java代码  收藏代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. import com.fruitking.proxy.CarService;  
  7.   
  8. public class TestSpringAOP {  
  9.   
  10.     /** 
  11.      * 利用spring的AOP机制实现“代理”的横向抽取机制方式 
  12.      * @param args 
  13.      */  
  14.     public static void main(String[] args) {  
  15.         ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");   
  16.         CarService carService = (CarService) ctx.getBean("carService");  
  17.         carService.start();  
  18.         carService.getLoadAmount();  
  19.         String driver = carService.setDriver("fruitking");  
  20.         System.out.println(driver);  
  21.         System.out.println("------------------------------");  
  22.         carService.loadGoods("Miss Mary");  
  23.         System.out.println("------------------------------");  
  24.         try{  
  25.             carService.loadGoods(null);  
  26.         }catch(NullPointerException e){  
  27.             e.printStackTrace();  
  28.         }  
  29.         System.out.println("------------------------------");  
  30.         try{  
  31.             carService.loadGoods("tiger");  
  32.         }catch(IllegalArgumentException e){  
  33.             e.printStackTrace();  
  34.         }  
  35.     }  
  36.   
  37. }  
  • proxy.rar (8.2 KB)
  • 下载次数: 106
0 0