这里我们学习一下代理模式,JDK的动态代理,以及以JDK为基础的springAOP实现
代理模式:类结构的模式,优点就是不需要更改原有类(被代理类)就能增强原有类(被代理类)的功能,缺点就是必须实现原有类(被代理类)的接口
JDK的动态代理:优点就是不必“复制”原有类(被代理类)接口实现类,缺点就是必须为每个被代理类实现几乎一样的方法
springAOP:优点就是采用springIOC,JDK动态代理等技术来实现AOP机制
我们展示一个类的几个方法,分别采用代理模式,JDK动态代理,springAOP机制来做些额外功能
这里定义一个接口,一个实现类
先来看看代理模式,定义一个代理类,然后调用代理类
再来看看JDK动态代理
{zh1}来看看spring的AOP机制的实现
spring的配置文件,把这些使用IOC处理
代理模式:类结构的模式,优点就是不需要更改原有类(被代理类)就能增强原有类(被代理类)的功能,缺点就是必须实现原有类(被代理类)的接口
JDK的动态代理:优点就是不必“复制”原有类(被代理类)接口实现类,缺点就是必须为每个被代理类实现几乎一样的方法
springAOP:优点就是采用springIOC,JDK动态代理等技术来实现AOP机制
我们展示一个类的几个方法,分别采用代理模式,JDK动态代理,springAOP机制来做些额外功能
这里定义一个接口,一个实现类
package com.fruitking.proxy; /** * 汽车服务类接口 * @author fruitking * @since 2010-02-23 */ public interface CarService { /** * 启动汽车 */ public void start(); /** * 获得汽车搭载人数 * @return */ public int getLoadAmount(); /** * 设置驾驶员 * @param driver * @return */ public String setDriver(String driver); /** * 搭载货物 * @param goods * @throws NullPointerException * @throws IllegalArgumentException */ public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException; }
package com.fruitking.proxy; /** * 汽车服务类接口实现 * @author fruitking * @since 2010-02-23 */ public class CarServiceImpl implements CarService{ /** * 启动汽车 */ public void start(){ System.out.println("start my car..."); } /** * 获得汽车搭载人数 * @return */ public int getLoadAmount(){ System.out.println("count the person amount in my car..."); return 5; } /** * 设置驾驶员 * @param driver * @return */ public String setDriver(String driver){ System.out.println("driver is:"+driver); if(driver==null||"".equals(driver)){ return "There is not driver."; }else{ return "The driver's name is " + driver + "."; } } /** * 搭载货物 * @param goods * @throws NullPointerException * @throws IllegalArgumentException */ public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{ if(goods==null||"".equals(goods)){ throw new NullPointerException("The argument goods is null."); }else if("tiger".equals(goods)){ throw new IllegalArgumentException("The argument goods is invalid."); } System.out.println("load goods is:"+goods); } }
先来看看代理模式,定义一个代理类,然后调用代理类
package com.fruitking.proxy.pattern; import com.fruitking.proxy.CarService; /** * 汽车服务类接口的代理类实现 * @author fruitking * @since 2010-02-23 */ public class CarServiceProxy implements CarService { private CarService carServiceTarget;//被代理的目标类 /** * 在构造函数中设置被代理的目标类 * 也可以使用set方法设置被代理的目标类 * @param carServiceTarget */ public CarServiceProxy(CarService carServiceTarget){ this.carServiceTarget = carServiceTarget; } /** * 启动汽车 */ public void start(){ System.out.println("before excute target object..."); carServiceTarget.start(); System.out.println("after excute target object..."); } /** * 获得汽车搭载人数 * @return */ public int getLoadAmount(){ System.out.println("before excute target object..."); int amount = carServiceTarget.getLoadAmount(); System.out.println("after excute target object..."); return amount; } /** * 设置驾驶员 * @param driver * @return */ public String setDriver(String driver){ System.out.println("before excute target object..."); String resultObject = carServiceTarget.setDriver(driver); System.out.println("after excute target object..."); return resultObject; } /** * 搭载货物 * @param goods * @throws NullPointerException * @throws IllegalArgumentException */ public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{ //这里不实现任何操作 } }
package com.fruitking.proxy.pattern; import com.fruitking.proxy.CarService; import com.fruitking.proxy.CarServiceImpl; public class TestProxyPattern { /** * 代理模式中的调用 * @param args */ public static void main(String[] args) { CarService carServiceTarget = new CarServiceImpl(); CarServiceProxy carServiceProxy = new CarServiceProxy(carServiceTarget); //执行代理类的方法 //作用一:间接执行被代理类的方法, //作用二:代理类可以在被代理类方法执行前后做一些额外操作 //总结:不更改原有类的功能和程序代码情况下,实现额外的功能能 //缺点:要为每个被代理类编写一个代理类,且需要实现相同接口的所有方法 carServiceProxy.start(); carServiceProxy.getLoadAmount(); String driver = carServiceProxy.setDriver("fruitking"); System.out.println(driver); } }
再来看看JDK动态代理
package com.fruitking.proxy.jdkdproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import com.fruitking.proxy.CarService; /** * java动态代理实现类 * @author fruitking * @since 2010-02-23 */ public class CarServiceJDKDynamicProxy implements InvocationHandler { private CarService carServiceTarget;//被代理的目标类 /** * 在构造函数中设置被代理的目标类 * 也可以使用set方法设置被代理的目标类 * @param carServiceTarget */ public CarServiceJDKDynamicProxy(CarService carServiceTarget){ this.carServiceTarget = carServiceTarget; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before excute target object..."); Object object = method.invoke(this.carServiceTarget,args); System.out.println("after excute target object..."); return object; } }
package com.fruitking.proxy.jdkdproxy; import java.lang.reflect.Proxy; import com.fruitking.proxy.CarService; import com.fruitking.proxy.CarServiceImpl; public class TestJDKDynamicProxy { /** * JDK中动态代理技术中的代理调用 * @param args */ public static void main(String[] args) { CarService carServiceTarget = new CarServiceImpl(); CarServiceJDKDynamicProxy carServiceJDKDynamicProxyTarget = new CarServiceJDKDynamicProxy(carServiceTarget); CarService carServiceProxy = (CarService)Proxy.newProxyInstance(carServiceTarget.getClass().getClassLoader(),new Class[]{CarService.class}, carServiceJDKDynamicProxyTarget); //执行代理类的方法 //作用一:间接执行被代理类的方法, //作用二:代理类可以在被代理类方法执行前后做一些额外操作 //总结:不更改原有类的功能和程序代码情况下,实现额外的功能能 //缺点:要为每个被代理类编写一个代理类,且具有相同的接口 carServiceProxy.start(); carServiceProxy.getLoadAmount(); String driver = carServiceProxy.setDriver("fruitking"); System.out.println(driver); } }
{zh1}来看看spring的AOP机制的实现
package com.fruitking.proxy.springaop; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; /** * 使用spring的AOP机制的事前通知接口实现 * @author fruitking * @since 2010-02-23 */ public class CarServiceBeforeAdvice implements MethodBeforeAdvice{ public void before(Method method, Object[] args, Object target)throws Throwable { System.out.println("before excute target object..."); String methodName = method.getName(); //得到方法名 String targetClassName = target.getClass().getName();//得到调用类名 System.out.println(targetClassName+"."+methodName+"()"); } }
package com.fruitking.proxy.springaop; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; /** * 使用spring的AOP机制的事前通知接口实现 * @author fruitking * @since 2010-02-23 */ public class CarServiceAfterAdvice implements AfterReturningAdvice { public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable{ String methodName = method.getName(); //得到方法名 String targetClassName = target.getClass().getName();//得到调用类名 System.out.println(targetClassName+"."+methodName+"()"); System.out.println("after excute target object..."); } }
package com.fruitking.proxy.springaop; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * 使用spring的AOP机制的事前通知接口实现 * @author fruitking * @since 2010-02-23 */ public class CarServiceAroundAdvice implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("before around excute target object..."); String methodName = invocation.getMethod().getName(); //得到方法名 String targetClassName = invocation.getClass().getName();//得到调用类名 System.out.println(targetClassName+"."+methodName+"()"); Object result = invocation.proceed(); //调用横切点,即真实操作 System.out.println("after around excute target object..."); return result; } }
package com.fruitking.proxy.springaop; import org.springframework.aop.ThrowsAdvice; /** * 使用spring的AOP机制的事前通知接口实现 * @author fruitking * @since 2010-02-23 */ public class CarServiceThrowsAdvice implements ThrowsAdvice { public void afterThrowing(NullPointerException e){//可以定义多个方法,只要传入的参数是不同异常 System.out.print("not load anything goods!"); } public void afterThrowing(IllegalArgumentException e){//可以定义多个方法,只要传入的参数是不同异常 System.out.print("load a tiger,it's very much dangerous!"); } }
spring的配置文件,把这些使用IOC处理
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="carServiceTarget" class="com.fruitking.proxy.CarServiceImpl"/> <bean id="carServiceBeforeAdvice" class="com.fruitking.proxy.springaop.CarServiceBeforeAdvice"/> <bean id="carServiceAfterAdvice" class="com.fruitking.proxy.springaop.CarServiceAfterAdvice"/> <bean id="carServiceAroundAdvice" class="com.fruitking.proxy.springaop.CarServiceAroundAdvice"/> <bean id="carServiceThrowsAdvice" class="com.fruitking.proxy.springaop.CarServiceThrowsAdvice"/> <bean id="carService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.fruitking.proxy.CarService"/> <property name="target" ref="carServiceTarget"/> <property name="interceptorNames"> <list> <value>carServiceBeforeAdvice</value> <value>carServiceAfterAdvice</value> <value>carServiceAroundAdvice</value> <value>carServiceThrowsAdvice</value> </list> </property> </bean> </beans>
package com.fruitking.proxy.springaop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.fruitking.proxy.CarService; public class TestSpringAOP { /** * 利用spring的AOP机制实现“代理”的横向抽取机制方式 * @param args */ public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); CarService carService = (CarService) ctx.getBean("carService"); carService.start(); carService.getLoadAmount(); String driver = carService.setDriver("fruitking"); System.out.println(driver); System.out.println("------------------------------"); carService.loadGoods("Miss Mary"); System.out.println("------------------------------"); try{ carService.loadGoods(null); }catch(NullPointerException e){ e.printStackTrace(); } System.out.println("------------------------------"); try{ carService.loadGoods("tiger"); }catch(IllegalArgumentException e){ e.printStackTrace(); } } }