Java动态代理之JDK

      本文由广州疯狂软件java培训分享:

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

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

  代码上,记得看注释哦

  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

  {

  @Override

  public void say(String name) {

  // TODO Auto-generated method stub

  System.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不是指向同一个对象吗?

  希望有大神可以指教我一下

  */

  }

  @Override

  public 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");

  /**

  * 结果是:

  * before

  MyOperationImpltest

  end

  */

  /**

  * 让我们来看一下具体的东西吧、这个 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指向的对象的父类是Proxy

  System.out.println(m.getClass().getInterfaces()[0].getName());

  //edu.fjnu.cs.hwb.proxypattern.MyOperation 这意味着m指向的类所实现的第一个接口的接口类

  //综上所述 通过 Proxy.newProxyInstance(loader, interfaces, h) 会利用第一个参数类加载器动态的产生一个Proxy的子类

  //并且实现了参数二的所有接口方法,当产生的对象调用了某个接口方法时,就会拦截下来,去调用h所拥有invoke方法

  //因此,这就有个缺陷,就是jdk的动态代理必须是接口的,如果一个类没有实现接口,那么就没有办法用动态代理,cglib的出现弥补了这个缺陷

  }

  }

  疯狂软件教育中心依托开发团队的强大技术实力,把企业最新技术融入实训课程,打造金牌的品质,才能给予学员黄金的未来,疯狂软件凭借过硬的技术实力与丰富的项目开发经验,赢得了社会的肯定。疯狂软件Java培训师资力量强大,课程内容深入,为学员高薪就业做了很好的铺垫,拥有丰富就业指导经验的就业团队也成为了学员高薪就业的先天优势。地址:广州天河区车陂沣宏大厦3楼。

原文地址:https://www.cnblogs.com/gojava/p/3614035.html