java动态代理学习笔记

xiaoxiao2021-03-01  2

转载,原作地址,请点击[java动态代理学习笔记],尊重原著,感谢langyu     

没事的时候翻看lang.reflect包下的代码,发现有两部分内容:涉及反射和动态代理。  很多地方都可以看到动态代理的影子,只是一直没仔细看下。  在学习之前,先提出几个问题,带着问题来看代码:  1.什么是动态代理? 2.为什么使用动态代理? 3.使用它有哪些好处? 4.哪些地方需要动态代理?  --------------------分隔线-----------------------------  和动态代理有关的有两个类  1.interface InvocationHandler  Object invoke(Object proxy, Method method, Object[] args)  只这一个方法,后面再说  2.class Proxy  真正表示动态代理的类,提供两个静态方法:  Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)  用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,  用来冒充真实的对象。  Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),  它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法,  invoke方法就是我们用来做N多事情的地方 -_-。  --------------------分隔线-----------------------------  看完上面的代码,大致明白动态代理的含义:  A接口有c方法,类B实现A接口,原本应该是执行B类中的c方法,可现在不这样做;  我声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口,  对外界来说B'应该也有c方法,可当真正调用它的时候,  它会去执行与它关联InvocationHandler的invoke()方法,  在这个方法里面你可以做很多事情。这样,这个请求就被“代理”到其它地方去了。  下面是根据我的理解画的一个说明图    --------------------分隔线-----------------------------  引用网上的一个例子来说明问题(有部分改动,转载自:http://callan.iteye.com/blog/161806)  真实的接口:  Java代码   public interface Hello {        void sayHello(String to);          void print(String p);      }   它的真实实现类:  Java代码   public class HelloImpl implements Hello {            public void sayHello(String to) {          System.out.println("Say hello to " + to);      }            public void print(String s) {          System.out.println("print : " + s);      }        }   在这里生成与代理类相关联的InvocationHandler对象  Java代码   public class LogHandler implements InvocationHandler {            private Object dele;            public LogHandler(Object obj) {          this.dele = obj;      }            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {          doBefore();          //在这里完全可以把下面这句注释掉,而做一些其它的事情          Object result = method.invoke(dele, args);          after();          return result;      }            private void doBefore() {          System.out.println("before....");      }            private void after() {          System.out.println("after....");      }  }   最后是测试类:  Java代码   public class ProxyTest {        public static void main(String[] args) {          HelloImpl impl = new HelloImpl();          LogHandler handler = new LogHandler(impl);          //这里把handler与impl新生成的代理类相关联          Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);                    //这里无论访问哪个方法,都是会把请求转发到handler.invoke          hello.print("All the test");          hello.sayHello("Denny");      }    }   这里是输出结果:  Java代码   before....  print : All the test  after....  before....  Say hello to Denny  after....   --------------------分隔线-----------------------------  最后试着来回答之前提出的问题:  1.什么是动态代理? 一种用于转发请求,进行特殊处理的机制,“动态”应该指的是“运行期”。 2.为什么使用动态代理? 可以对请求进行任何处理(如事务,日志等,这都是网上说的,我当然可以做任何处理) 3.使用它有哪些好处? 如上 4.哪些地方需要动态代理? 不允许直接访问某些类;对访问要做特殊处理等,我只能想到这些。  --------------------分隔线-----------------------------  其它一些想法:  1.如果想声明产生B类的代理类,那个B类必须要实现接口,如果没有接口,  代理类就不能伪装成B类的“兄弟”,也就没有存在的意思,  其实也可以伪装成B类的“孩子”,对外他们有共同的接口,可以这样做吧?  2.当请求代理类的方法时,这个请求会被转到执行与代理类关联InvocationHandler  的invoke方法。那InvocationHandler到底是什么?对它的理解可以是这样:  它用来处理方法的调用,实现类也有同样的意义;与代理类对象相关联则表示,  它就是负责处理代理类应该有的动作,把所有的方法请求分发到invoke这个方法上。  --------------------分隔线-----------------------------  学习后总结,既可以全面地观察分析,又能加深印象。  如果我的理解有误,别人的指证会对我产生积极影响。  如果我的理解正确,帮助其它人理解是我的荣幸。  初学者,请多多指教。
转载请注明原文地址: https://www.6miu.com/read-3650185.html

最新回复(0)