在现实生活中,我们常见的有服务器代理商、联想PC代理商、百事可乐、火车票、机票等代理商,为什么会有这些个代理商呢?设想以买火车票为场景,如果我要买一张从广州去长沙的火车票,就必须去火车站排队购票,如果排队的人比较多的话,非常的耽误时间。但有了火车票代理商之后,我就可以直接去找个离我最近的代理商买票,因为这样的代理商不止一个二个,遍布全市各地。 所以代理商的出现不但减轻了火车站售票员的工作压力,同时也为市民购票提供了许多方便。只是代理商会收5块的手续费。从这个示例中可以发现和买票有关的一些名词:火车站、售票、代理商?解释这些名词在程序中代理的含义:火车站:称为目标,售票:目标的最终行为,代理商:和火车站具有同样售票行为的代理商,不过代理商在售票前和售票后会做一些操作,比如查询余票、售票后收取手续费等操作。
package proxy; public interface Ticket { public void ticket(); }b、售票接口的实现类
package proxy; public class TicketImpl implements Ticket { @Override public void ticket() { System.out.println("成功售出一张火车票!"); } }c、火车票销售的代理类,与目标类实现了相同的接口
package proxy; /** * 火车票销售代理类 */ public class TicketImplProxy implements Ticket { private TicketImpl ticketImpl; //目标类 public TicketImplProxy(TicketImpl ticketImpl) { this.ticketImpl = ticketImpl; } @Override public void ticket() { System.out.println("售票前验证顾客的身份信息…………"); ticketImpl.ticket(); System.out.println("售票后收取顾客的手续费…………"); } }d、测试类:
package proxy; public class StaticProxyTest { public static void main(String[] args) throws Exception { TicketImpl ticketImpl = new TicketImpl(); //要代理的目标 TicketImplProxy staticProxy = new TicketImplProxy(ticketImpl); staticProxy.ticket(); } }
Class clazzProxy = Proxy.getProxyClass(ArrayList.class.getClassLoader(), ArrayList.class.getInterfaces());
System.out.println("代理类名称:" + clazzProxy.getName());
System.out.println("代理类" + clazzProxy.getName() + "的父类:" + clazzProxy.getSuperclass().getName());代理类$Proxy0的父类:java.lang.reflect.Proxy
Class[] clazzInterfaces = clazzProxy.getInterfaces(); StringBuilder sbInterfaces = new StringBuilder(); for (Class clazzInterface : clazzInterfaces) { sbInterfaces.append(clazzInterface.getName()).append(","); } sbInterfaces.deleteCharAt(sbInterfaces.length()-1); System.out.println("代理类" + clazzProxy.getName() + "所实现的接口:" + sbInterfaces);代理类$Proxy0所实现的接口:java.util.List,java.util.RandomAccess,java.lang.Cloneable,java.io.Serializable
System.out.println("代理类" + clazzProxy.getName() + "的访问修饰符:" + clazzProxy.getModifiers());代理类$Proxy0的访问修饰符:17
System.out.println("\n-------------打印代理类" + clazzProxy.getName() + "的构造方法列表-------------"); Constructor[] constructors = clazzProxy.getConstructors(); for (Constructor constructor : constructors) { System.out.println("访问修饰符:" + constructor.getModifiers()); String name = constructor.getName(); int modifiers = constructor.getModifiers(); StringBuilder sb = new StringBuilder(name); sb.append('('); Class[] clazzParameters = constructor.getParameterTypes(); for (Class clazzParameter : clazzParameters) { sb.append(clazzParameter.getName()).append(","); } if (clazzParameters != null && clazzParameters.length != 0) { sb.deleteCharAt(sb.length()-1); } sb.append(')'); System.out.println(sb.toString()); }-------------打印代理类$Proxy0的构造方法列表-------------
System.out.println("\n-------------打印代理类" + clazzProxy.getName() + "的方法列表-------------"); Method[] methods = clazzProxy.getMethods(); for (Method method : methods) { String name = method.getName(); StringBuilder sb = new StringBuilder(name); sb.append('('); Class[] clazzParameters = method.getParameterTypes(); for (Class clazzParameter : clazzParameters) { sb.append(clazzParameter.getName()).append(","); } if (clazzParameters != null && clazzParameters.length != 0) { sb.deleteCharAt(sb.length()-1); } sb.append(')'); System.out.println(sb.toString()); }
-------------打印代理类$Proxy0的方法列表------------- add(java.lang.Object) add(int,java.lang.Object) get(int) equals(java.lang.Object) toString() hashCode() indexOf(java.lang.Object) clear() contains(java.lang.Object) isEmpty() lastIndexOf(java.lang.Object) addAll(java.util.Collection) addAll(int,java.util.Collection) iterator() size() toArray() toArray([Ljava.lang.Object;) remove(java.lang.Object) remove(int) set(int,java.lang.Object) containsAll(java.util.Collection) removeAll(java.util.Collection) retainAll(java.util.Collection) subList(int,int) listIterator() listIterator(int) isProxyClass(java.lang.Class) getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;) getInvocationHandler(java.lang.Object) newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler) wait(long) wait() wait(long,int) getClass() notify() notifyAll()
//由上述信息可推断出代理类的文件结构(程序中只实现打印代理类的声明部份) StringBuilder sbProxyClassStruct = new StringBuilder("public final class "); sbProxyClassStruct.append(clazzProxy.getName()) .append(" extends ").append(clazzProxy.getSuperclass().getName()) .append(" implements ").append(sbInterfaces).append(" { } "); System.out.println("代理类的结构:" + sbProxyClassStruct);程序中只打印了代理类的声明部份,结果:
package proxy; import java.lang.reflect.InvocationHandler; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public final class $Proxy0 extends java.lang.reflect.Proxy implements java.util.List, java.util.RandomAccess, java.lang.Cloneable, java.io.Serializable { public $Proxy0(InvocationHandler h) { super(h); // TODO Auto-generated constructor stub } @Override public boolean add(Object e) { // TODO Auto-generated method stub return false; } @Override public void add(int index, Object element) { // TODO Auto-generated method stub } @Override public boolean addAll(Collection c) { // TODO Auto-generated method stub return false; } @Override public boolean addAll(int index, Collection c) { // TODO Auto-generated method stub return false; } @Override public void clear() { // TODO Auto-generated method stub } @Override public boolean contains(Object o) { // TODO Auto-generated method stub return false; } @Override public boolean containsAll(Collection c) { // TODO Auto-generated method stub return false; } @Override public Object get(int index) { // TODO Auto-generated method stub return null; } @Override public int indexOf(Object o) { // TODO Auto-generated method stub return 0; } @Override public boolean isEmpty() { // TODO Auto-generated method stub return false; } @Override public Iterator iterator() { // TODO Auto-generated method stub return null; } @Override public int lastIndexOf(Object o) { // TODO Auto-generated method stub return 0; } @Override public ListIterator listIterator() { // TODO Auto-generated method stub return null; } @Override public ListIterator listIterator(int index) { // TODO Auto-generated method stub return null; } @Override public boolean remove(Object o) { // TODO Auto-generated method stub return false; } @Override public Object remove(int index) { // TODO Auto-generated method stub return null; } @Override public boolean removeAll(Collection c) { // TODO Auto-generated method stub return false; } @Override public boolean retainAll(Collection c) { // TODO Auto-generated method stub return false; } @Override public Object set(int index, Object element) { // TODO Auto-generated method stub return null; } @Override public int size() { // TODO Auto-generated method stub return 0; } @Override public List subList(int fromIndex, int toIndex) { // TODO Auto-generated method stub return null; } @Override public Object[] toArray() { // TODO Auto-generated method stub return null; } @Override public Object[] toArray(Object[] a) { // TODO Auto-generated method stub return null; } }
//方式1,创建一个内部类,并实现InvocationHandler接口 Constructor proxy1 = clazzProxy.getConstructor(InvocationHandler.class); System.out.println("------------创建代理类实例,方式1--------------------"); class MyInvocationHandler implements InvocationHandler { ArrayList target = new ArrayList(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); System.out.println(name + "方法调用前..."); Object retVal = method.invoke(target, args); System.out.println(name + "方法调用后的返回结果为:" + retVal); System.out.println(name + "方法调用后...\n"); return retVal; } } List list1 = (List)proxy1.newInstance(new MyInvocationHandler()); list1.add("zhangsan"); list1.add("lisi"); System.out.println(list1.size());调用List接口的add方法和size方法后的输出结果:
//方式2 Constructor prox2 = clazzProxy.getConstructor(InvocationHandler.class); List list2 = (List)prox2.newInstance(new InvocationHandler() { List target = new ArrayList(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object retVal = method.invoke(target, args); return retVal; }} );
//方式3(匿名类),将创建代理类和创建代理类实例对象的步聚合二为一 System.out.println("------------创建代理类实例,方式3--------------------"); List list3 = (List)Proxy.newProxyInstance( ArrayList.class.getClassLoader(), ArrayList.class.getInterfaces(), new InvocationHandler() { ArrayList target = new ArrayList(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //测试方法的运行效率 long beginTime = System.currentTimeMillis(); Object retVal = method.invoke(target, args); long endTime = System.currentTimeMillis(); System.out.println(method.getName() + " 方法运行时长为:" + (endTime - beginTime)); return retVal; }} ); list3.add("hy"); list3.add("yangxin"); System.out.println(list3.size());输出结果:
/** * 获得代理对象 * @param target 目标(被代理的对象) * @param advice 目标对象中的方法被调用前要执行的功能 * @return 目标的代理对象 */ private static Object getProxy(final Object target,final Advice advice) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object retVal = null; try { advice.doBefore(target, method, args);//方法执行前 retVal = method.invoke(target, args); advice.doAfter(target, method, args, retVal);//方法执行后 } catch (Exception e) { advice.doThrow(target, method, args, e);//方法抛出异常 } finally { advice.doFinally(target, method, args);//方法最终执行代码(用于释放数据资源、关闭IO流等操作) } return retVal; }} ); }封装功能的对象:
package proxy; import java.lang.reflect.Method; /** * aop接口,提供方法运行前、方法运行后、方法运行中产生Exception、方法最终运行代码 * */ public interface Advice { /** * 方法运行前 * @param target 被代理的目标对象 * @param method 被调用的方法 * @param args 方法的参数 */ public void doBefore(Object target, Method method, Object[] args); /** * 方法运行后 * @param target 被代理的目标对象 * @param method 被调用的方法对象 * @param args 方法的参数 * @param retVal 方法的返回值 */ public void doAfter(Object target, Method method, Object[] args, Object retVal); /** * 方法运行时产生的异常 * @param target 被代理的目标对象 * @param method 被调用的方法 * @param args 方法参数 * @param e 运行时的异常对象 */ public void doThrow(Object target, Method method, Object[] args, Exception e); /** * 最终要执行的功能(如释放数据库连接的资源、关闭IO流等) * @param target 被代理的目标对象 * @param method 被调用的方法 * @param args 方法参数 */ public void doFinally(Object target, Method method, Object[] args); }再建一个日志功能的实现类LogAdvice,用于测试:
package proxy; import java.lang.reflect.Method; import java.util.Arrays; /** * 日志功能切入类 * @author 杨信 * */ public class LogAdvice implements Advice { long beginTime = System.currentTimeMillis(); @Override public void doBefore(Object target, Method method, Object[] args) { System.out.println(target.getClass().getSimpleName() + "." + method.getName() + "方法被调用,参数值:" + Arrays.toString(args)); } @Override public void doAfter(Object target, Method method, Object[] args, Object retVal) { long endTime = System.currentTimeMillis(); System.out.println(target.getClass().getSimpleName() + "." + method.getName() + "方法运行结束,返回值:" + retVal + ",耗时" + (endTime - beginTime) + "毫秒。"); } @Override public void doThrow(Object target, Method method, Object[] args, Exception e) { System.out.println("调用" + target.getClass().getSimpleName() + "." + method.getName() + "方法发生异常,异常消息:"); e.printStackTrace(); } @Override public void doFinally(Object target, Method method, Object[] args) { System.out.println("doFinally..."); } }
ArrayList target = new ArrayList(); List list4 = (List)getProxy(target,new LogAdvice()); list4.add("张三"); list4.add("李四"); list4.add("王五"); System.out.println(list4.size()); list4.get(3); //演示异常advice
ArrayList.add方法被调用,参数值:[张三] ArrayList.add方法运行结束,返回值:true,耗时0毫秒。 doFinally... ArrayList.add方法被调用,参数值:[李四] ArrayList.add方法运行结束,返回值:true,耗时0毫秒。 doFinally... ArrayList.add方法被调用,参数值:[王五] ArrayList.add方法运行结束,返回值:true,耗时0毫秒。 doFinally... ArrayList.size方法被调用,参数值:null ArrayList.size方法运行结束,返回值:3,耗时0毫秒。 doFinally... 3 ArrayList.get方法被调用,参数值:[3] 调用ArrayList.get方法发生异常,异常消息: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at proxy.DynamicProxyTest$3.invoke(DynamicProxyTest.java:163) at $Proxy0.get(Unknown Source) at proxy.DynamicProxyTest.main(DynamicProxyTest.java:143) Caused by: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) ... 7 more doFinally...完毕,通过动态代理机制,实现了传说中的AOP思想。