首页 > 其他 > 详细

Proxy.newProxyInstance内幕

时间:2016-02-22 02:06:15      阅读:2251      评论:0      收藏:0      [点我收藏+]
 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
            throws IllegalArgumentException {
        //InvocationHandler不能为空,因为对代理对象的所有方法调用实际上都会委托到InvocationHandler的invoke方法,
        //这个我们后面通过查看产生的代理类的源代码便会一目了然
        if (h == null) {
            throw new NullPointerException();
        }

        //这个是核心的地方,通过提供的ClassLoader和interface列表来产生代理类,具体的实现可以参考getProxyClass这个方法的实现,
        //真正的工作是由sun.misc.ProxyGenerator这个类来完成的,可以google查看具体的逻辑.在我们的程序中通过设置
        //System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")可以查看产生的类文件
        Class cl = getProxyClass(loader, interfaces);

        //因为代理类继承了Proxy类.而Proxy中定义了构造函数protected Proxy(InvocationHandler h),所以可以反射得到Constructer实例
        //创建代理对象
        try {
            Constructor cons = cl.getConstructor(constructorParams);
            return (Object) cons.newInstance(new Object[] { h });
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString());
        } catch (IllegalAccessException e) {
            throw new InternalError(e.toString());
        } catch (InstantiationException e) {
            throw new InternalError(e.toString());
        } catch (InvocationTargetException e) {
            throw new InternalError(e.toString());
        }
    }

?

public interface Subject {
    void pub(String key, String content);

    String sub(String key);
}


public class SimpleSubject implements Subject {
    private Map<String, String> msg = new ConcurrentHashMap<String, String>();

    public void pub(String key, String content) {
        System.out.println("pub msg: key is " + key + ", content is " + content);
        msg.put(key, content);
    }

    public String sub(String key) {
        if (msg.containsKey(key)) {
            String ret = msg.get(key);
            System.out.println("sub msg: key is " + key + ", result is " + ret);
            return ret;
        }

        return null;
    }

}


public class SubjectProxyFactory {
    //TODO: cache 
    public static Subject getSubject(final Subject realSubject) {
        return (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), new Class[] { Subject.class },
                new InvocationHandler() {

                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("\naction before method invocation....");
                        Object retVal = method.invoke(realSubject, args);
                        System.out.println("action after method invocation....\n");
                        return retVal;
                    }
                });
    }
}


public class Demo {
    public static void main(String[] args) {
        //设置此系统属性,以查看代理类文件
        System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        
        //创建真实对象
        Subject subj = new SimpleSubject();
        subj.pub("name", "kevin.fan");
        subj.sub("name");
        
        //创建代理对象
        Subject proxy = SubjectProxyFactory.getSubject(subj);
        proxy.pub("hobby", "r&b music");
        proxy.sub("name");
    }
}

?

pub msg: key is name, content is kevin.fan
sub msg: key is name, result is kevin.fan

action before method invocation....
pub msg: key is hobby, content is r&b music
action after method invocation....

action before method invocation....
sub msg: key is name, result is kevin.fan
action after method invocation….

?

//这里很清楚了,代理类继承了Proxy类,并且实现了Proxy.newProxyInstance这个方法中传入的接口
public final class $Proxy0 extends Proxy
  implements Subject
{
  
  //这些方法在下面的static init block中进行初始化
  private static Method m4;
  private static Method m1;
  private static Method m3;
  private static Method m0;
  private static Method m2;
  
  static
  {
    try
    {
      m4 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("sub", new Class[] { Class.forName("java.lang.String") });
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("pub", new Class[] { Class.forName("java.lang.String"), Class.forName("java.lang.String") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }

  //构造函数,接收一个 InvocationHandler作为参数,这就是为什么Proxy.newProxyInstance方法里可以
  //通过InvocationHandler实例作为参数来反射获取Constructer实例 
  public $Proxy0 paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  //下面通过这个来看下代理对象中方法是怎样调用的
  public final String sub(String paramString)
    throws 
  {
    try
    {
       //全部是通过调用InvocationHandler的invoke方法,传入对应的方法和参数
      return (String)this.h.invoke(this, m4, new Object[] { paramString });
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final void pub(String paramString1, String paramString2)
    throws 
  {
    try
    {
      this.h.invoke(this, m3, new Object[] { paramString1, paramString2 });
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

}

?

Sring AOP里最重要的两个概念是增强(Advice)和切面(Advisor),增强是织入到目标类连接点上的一段程序代码,切面决定要给什么类的什么方法实施增强。是怎么做到对特定方法实施增强的呢?对invoke方法中的method#name进行判断。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("\naction before method invocation....");
                        Object retVal = method.invoke(realSubject, args);
                        System.out.println("action after method invocation....\n");
                        return retVal;
                    }

? ? Spring提供了ProxyFactoryBean创建代理,及利用BeanPostProcessor实现自动创建代理。

?

? ? Spring是在运行期利用JDK或CGLib创建代理,我们还可以在类加载期间通过字节码编辑的技术,将切面织入到目标类中,这种织入方式称为LTW(Load Time Weaving)。Spring为LTW的过程提供了细粒度的控制,它支持在单个ClassLoader范围内实施类文件转换,且配置更为简单。

Proxy.newProxyInstance内幕

原文:http://wely.iteye.com/blog/2277881

(0)
(3)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!