------- android培训、java培训、期待与您交流! ----------
什么是代理?代理就是对目标对象提供一种代理以控制对这个对象的访问,像这些术语什么的最讨厌了,虽然表述正确,但是很难记,还是用通俗的话来概括一下,
我认为代理就是通过一个类访问另外一个类。
代理类与目标类(委托类)有同样的接口,代理是为了给目标类提供额外的处理或者不同的操作,如异常处理、运行时间、日志、事物管理等。
代理类的对象本身并不真正实现服务,而是通过调用目标类/委托类对象的相关方法提供服务。
有没有想起设计模式中的代理模式,是的,今天要讲的代理其实和设计模式中的代理模式从本质上来讲是一样的。
使用代理的目的主要的目的是为了对目标类,进行精确的控制。
我们在调用某个类的某个方法时,不仅要的到方法调用后的结果,还想再调用方法前后加上自己定义的一段程序并执行,这时使用代理技术就很方便了。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
也就是说,静态代理类运行前就有,动态代理类运行时才出现。
如果使用静态代理的话,我们就需要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情。
所以我们主要采用的是动态代理的方式。包括一些框架也是通过动态代理实现的。
//返回代理类的Class对象,参数(类加载器,实现的接口) Class clazzProxy = Proxy.getProxyClass( Collection.class.getClassLoader(), Collection.class);
private static void CreatConstructor(Class clazzProxy) { Constructor[] cons = clazzProxy.getConstructors(); for (Constructor constructor : cons) { String name = constructor.getName(); StringBuilder sb = new StringBuilder(name); sb.append('('); Class[] cls = constructor.getParameterTypes(); for (Class class1 : cls) { sb.append(class1.getName()).append(','); } sb.append(')'); System.out.println(sb + "......"); } }
private static void CreatMethod(Class clazzProxy) { Method[] methods = clazzProxy.getMethods(); for (Method method : methods) { String name = method.getName(); StringBuilder sb = new StringBuilder(name); sb.append('('); Class[] cls = method.getParameterTypes(); for (Class class1 : cls) { sb.append(class1.getName()).append(','); } sb.append(')'); System.out.println(sb + "......"); } }
private static void InstanceObj1(Class clazzProxy) throws Exception { // 根据creatConstructor()方法可知clazzProxy无构造方法 //InvocationHandler:是代理实例的调用处理程序实现的接口。 仅包含一个方法invoke Constructor con = clazzProxy.getConstructor(InvocationHandler.class); //通过内部类形式实现该方法 class MyInvocation implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在这里写调用的Target(目标类)的具体操作 return null; } } Collection proxy1 = (Collection) con.newInstance(new MyInvocation()); System.out.println(proxy1); }
/** * 获得一个动态代理类,改写,通过匿名内部类 * */ private static void InstanceObj2(Class clazzProxy) throws Exception { // 根据creatCOnstructor()方法可知clazzProxy无构造方法 Constructor con = clazzProxy.getConstructor(InvocationHandler.class); Object proxy1 = con.newInstance(new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } }); System.out.println(proxy1); }
/** * 获得一个动态代理类,通过Proxy.newProxyInstance()方法 */ private static void InstanceObj3() { Collection proxy1 = (Collection) Proxy.newProxyInstance( Collection.class.getClassLoader(),//第一个参数,定义代理类的类加载器 new Class[] { Collection.class}, //第二个参数,代理类要实现的接口列表 new InvocationHandler() { //第三个参数,指派方法调用的调用处理程序 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ArrayList target = new ArrayList(); return method.invoke(target, args); } }); }
这副图还是很形象的,在画圈的部分添加自己的代码,客户端通过调用动态代理类的某方法,通过InvocationHandler接口的invoke()方法调用Target(目标类)的同相同方法。
package cn.jinfulin.day3.Proxy; import java.lang.reflect.Method; public interface IAdvice { void beforMethod(Method method); void afterMethod(Method method); }
package cn.jinfulin.day3.Proxy; import java.lang.reflect.Method; public class MyAdvice implements IAdvice { long beginTime; @Override public void beforMethod(Method method) { beginTime = System.currentTimeMillis(); System.out.println(method.getName() + "欢迎来学习动态代理,"); } @Override public void afterMethod(Method method) { Long endTime = System.currentTimeMillis(); System.out.println( method.getName() + "我已经学会了代理,用时" + (endTime - beginTime)); } }
/** * 最终改写后的代理类 */ private static Object finnalMethod(final Object target,final IAdvice advice) { Object proxy1 = Proxy.newProxyInstance(//创建动态代理类的一个新实例 target.getClass().getClassLoader(),//第一个参数,定义代理类的类加载器 target.getClass().getInterfaces(), //第二个参数,代理类要实现的接口列表 new InvocationHandler() { //第三个参数,指派方法调用的调用处理程序 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { advice.beforMethod(method);//加上目标类的一个方法 Object retval = method.invoke(target, args); advice.afterMethod(method);//在加上目标类的一个方法 return retval; // return method.invoke(target, args); } }); return proxy1; }
ArrayList target = new ArrayList(); Collection proxy = (Collection)finnalMethod(target,new MyAdvice()); proxy.add("金福林");//使用了一次方法,就相当于调用了一次invoke方法 proxy.clear();\\第二次调用 System.out.println(proxy.size());\\第三次调用
代理终于也写完了,以后要靠java吃饭,java基础学好了还是很有必要的,以后的开发也是在这些知识基础上,使用框架和API等做开发。毕竟万变不离其宗,掌握基础掌握原理才能更好的使用工具。
原文:http://blog.csdn.net/jinfulin/article/details/44967635