Java动态代理之JDK

来源:互联网 发布:linux 修改profile 编辑:程序博客网 时间:2024/04/30 19:49

昨天和今天学习了Java的动态代理。现在让我总结一下。

首先先让我们谈一下一种设计模式:  代理模式

详情请看:http://blog.csdn.net/hwb1992/article/details/20538921

现在让我们来讨论一下动态代理

代码上,记得看注释哦

package edu.fjnu.cs.hwb.proxypattern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;interface MyOperation //定义了所有的接口方法{void say(String name);}class MyOperationImpl implements MyOperation{@Overridepublic void say(String name) {// TODO Auto-generated method stubSystem.out.println("MyOperationImpl"+name);}}class MyInvocationHandler implements InvocationHandler{private Object obj;public MyInvocationHandler(Object obj){this.obj = obj;//其实,我在这里也有个疑问,为什么要把目标对象放在这里面,我试过不用这句话,然后执行的话会报错,内容就是/* * at edu.fjnu.cs.hwb.proxypattern.$Proxy0.say(Unknown Source)at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:597)at edu.fjnu.cs.hwb.proxypattern.MyInvocationHandler.invoke(JDKProxy.java:35)从中我推测出,JDK不知道目标对象是谁,因此这句话就是设置目标对象当我添加这句话之后,我调试运行,发现那个invoke的参数proxy居然和我的属性obj是一模一样的,但是没有添加这句话之前就不是了 。 但是如果我下面写得是 method.invoke(proxy, args); 那么还是会报错!!我觉得好奇怪。obj和proxy不是指向同一个对象吗?希望有大神可以指教我一下 */}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("before");Object result = method.invoke(obj, args);//调用的是目标类的方法    第一个参数是目标对象的引用System.out.println("end");return result ;}}public class JDKProxy{public static void main(String[] args){MyOperation myoperation = new MyOperationImpl();//产生目标类MyInvocationHandler myhandler = new MyInvocationHandler(myoperation);//产生一个InvocationHandler的子类对象,并且重写invoke方法                //以及在其中添加了目标类引用  MyOperation m =            (MyOperation) Proxy.newProxyInstance(myoperation.getClass().getClassLoader(),myoperation.getClass().getInterfaces(),myhandler);//产生了一个代理类,第一个参数表示的是用哪个类加载器//第二个参数表示目标类的所有接口方法//第三个参数表示我会调用这个参数的invoke方法m.say("test");/** * 结果是: * beforeMyOperationImpltestend *//** * 让我们来看一下具体的东西吧、这个 m  到底是什么东西 */System.out.println(m.getClass().getName());//edu.fjnu.cs.hwb.proxypattern.$Proxy0    这意味着m指向的对象是一个Proxy子类System.out.println(m.getClass().getSuperclass().getName());//java.lang.reflect.Proxy   m指向的对象的父类是ProxySystem.out.println(m.getClass().getInterfaces()[0].getName());//edu.fjnu.cs.hwb.proxypattern.MyOperation     这意味着m指向的类所实现的第一个接口的接口类//综上所述   通过Proxy.newProxyInstance(loader, interfaces, h) 会利用第一个参数类加载器动态的产生一个Proxy的子类           //并且实现了参数二的所有接口方法,当产生的对象调用了某个接口方法时,就会拦截下来,去调用h所拥有invoke方法//因此,这就有个缺陷,就是jdk的动态代理必须是接口的,如果一个类没有实现接口,那么就没有办法用动态代理,cglib的出现弥补了这个缺陷}}



0 0