答:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。
答:因为动态代理可以对请求进行任何处理
答:因为动态代理可以对请求进行任何处理
答:不允许直接访问某些类;对访问要做特殊处理等
目前Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。 其实现主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。
Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现
以下为模拟案例,通过动态代理实现在方法调用前后向控制台输出两句字符串
目录结构:
实例代码:
package com.ren.day03; import java.lang.reflect.Method; //代理类接口 public interface Advice { void beforeMehtod(Method method); void afterMehtod(Method method); }
package com.ren.day03; import java.lang.reflect.Method; public class MyAdvice implements Advice { private long start = 0; private long end = 0; @Override public void beforeMehtod(Method method) { // TODO Auto-generated method stub System.out.println("方法调用前"); start = System.currentTimeMillis(); } @Override public void afterMehtod(Method method) { // TODO Auto-generated method stub end = System.currentTimeMillis(); System.out.println(method.getName() + "run time :" + (end - start)); System.out.println("方法调用后"); } }
package com.ren.day03; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; public class ProxyTest { /** * @param args * @throws NoSuchMethodException * @throws SecurityException * @throws InvocationTargetException * @throws IllegalAccessException * @throws InstantiationException * @throws IllegalArgumentException */ public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { // TODO Auto-generated method stub Class clazzProxy = Proxy.getProxyClass( Collection.class.getClassLoader(), Collection.class); System.out.println(clazzProxy.getName()); System.out.println("---------Begin constructor list---------"); Constructor[] constructors = clazzProxy.getConstructors(); for (Constructor constructor : constructors) { String name = constructor.getName(); StringBuilder sb = new StringBuilder(name); sb.append("("); Class[] clazzParaType = constructor.getParameterTypes(); for (Class clazzPara : clazzParaType) { sb.append(clazzPara.getName()); sb.append(","); } if (clazzParaType.length != 0) sb.deleteCharAt(sb.length() - 1); sb.append(")"); System.out.println(sb.toString()); } System.out.println("---------Begin method list---------"); Method[] methods = clazzProxy.getMethods(); for (Method method : methods) { String name = method.getName(); StringBuilder sb = new StringBuilder(name); sb.append("("); Class[] clazzParaType = method.getParameterTypes(); for (Class clazzPara : clazzParaType) { sb.append(clazzPara.getName()); sb.append(","); } if (clazzParaType.length != 0) sb.deleteCharAt(sb.length() - 1); sb.append(")"); System.out.println(sb.toString()); } System.out.println("-----------Create instance object--------------"); // clazzProxy.newInstance(); //得到构造器 Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class); //实现InvocationHandler接口 class MyInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return null; } } //创建实例对象1 Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHandler()); //调用方法 System.out.println(proxy1); System.out.println(proxy1.toString()); //从toString方法可以看出创建实例对象成功,至于打印为什么是null,是因为toString方法返回null //创建实例对象2,用内部类实现InvocationHandler接口 Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return null; } }); //创建实例对象3,直接用Rroxy,newProxyInstance方法 /*Collection proxy3 = (Collection)Proxy.newProxyInstance( Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler() { ArrayList target = new ArrayList(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("方法调用前"); long start = System.currentTimeMillis(); Object obj = method.invoke(target, args); long end = System.currentTimeMillis(); System.out.println(method.getName() + "run time :" + (end - start)); System.out.println("方法调用后"); return obj; } });*/ final ArrayList target = new ArrayList(); Collection proxy3 = getProxy(target,new MyAdvice()); //再次调用方法 proxy3.add("fff"); proxy3.add("fff"); proxy3.add("fff"); System.out.println(proxy3.size()); } //创建实例对象3,直接用Rroxy,newProxyInstance方法 public static Collection getProxy(final ArrayList target,final Advice advice) { Collection proxy3 = (Collection)Proxy.newProxyInstance( Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub advice.beforeMehtod(method); //通过对象传入方法 Object obj = method.invoke(target, args); advice.afterMehtod(method); return obj; } }); return proxy3; } }