黑马程序员——java加强之代理

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

代理

一、 静态代理,一般分为 类继承代理与对象组合代理。 类继承就是继承超类获得超类的功能。

在应用中,一般用组合代理。

如下图:

 

 二、在java应用中,动态代理应用更广泛,可以说这是java语言的特性。

 

public class SetProxyFactory {

         @SuppressWarnings("unchecked")

         publicstatic <T> T getProxy(final T obj) {

                   //类加载器、类的接口、一个InvocationHandler实现

                   return(T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj

                                     .getClass().getInterfaces(),new InvocationHandler() {

                            publicObject invoke(Object proxy, Method method, Object[] args)

                                               throwsThrowable {

                                     System.out.println("Start....");

                                     returnmethod.invoke(obj, args);

                            }

                   });

         }

         publicstatic void main(String[] agrs) throws ClassNotFoundException {

                   Set<String>set = new HashSet<String>();// 创建一个类

                   Set<String>proxySet = SetProxyFactory.getProxy(set);// 有类生成一个代理对象

                   System.out.println(Proxy.getInvocationHandler(proxySet));

                   System.out.println(proxySet.size());

         }

}

  1. 动态代理主要涉及到 Proxy类与InvocationHandler类。
    1. Proxy有一个 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)返回值是一个由JVM动态生成的类所实例化的对象,可以认为InvocationHandler 是这个类的变量属性。
      1. loader是类加载器
      2. interfaces 是接口列表
      3. InvocationHandler 是一个InvocationHandler 的实例。
    2. InvocationHandler有一个接口: public Object invoke(Object proxy, Method method, Object[] args)  throws Throwable;此接口可以认为是回调函数,也就是代理的类的对象 被访问时候,就会触发它所绑定的 InvocationHandler 的invoke方法。传来的差数有代理类,方法,差数列表。在invoke方法一般有method.invoke(obj, args)调用,obj真正的实例。
  2. 动态关键类还是Proxy类的newProxyInstance方法,我们可以进入源码一看究竟。

 

public static ObjectnewProxyInstance(ClassLoader loader,

                                                 Class<?>[] interfaces,

                                                 InvocationHandler h)

         throwsIllegalArgumentException

    {

         if(h == null) {

             throw new NullPointerException();

         }

 

         /*

          * Look up or generate the designated proxyclass.

          */

         Classcl = getProxyClass(loader, interfaces);//关键是创建代理类

 

         /*

          * Invoke its constructor with the designatedinvocation handler.

          */

         try{

             Constructor cons =cl.getConstructor(constructorParams);

             return (Object) cons.newInstance(newObject[] { h });//InvocationHandler是作为一个实例变量传入代理类中。

         }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());

         }

}

关键还是 Classcl = getProxyClass(loader, interfaces); getProxyClass方法,该方法的差数是 ClassLoader 与 Classinterfaces。此方法中主要分为:

  1. 检查 ,一般有:接口数目不能大于65535,禁止非接口,禁止有重复的接口等。
  2. 缓存并复用。
  3. 定义名称 

long num;

                   synchronized(nextUniqueNumberLock) {

                       num = nextUniqueNumber++;

                   }

                   String proxyName = proxyPkg +proxyClassNamePrefix + num;

5创建代理类。代码如下

/*

                    * Generate the specified proxy class.

                    */

                   byte[]proxyClassFile =     ProxyGenerator.generateProxyClass(

                       proxyName, interfaces); 主要是此方法,生成了 字节码。 如果要看,建议使用openjdk及看看jvm字节码

                   try{

                       proxyClass = defineClass0(loader,proxyName,

                            proxyClassFile,0, proxyClassFile.length);

  1.  
    1. 最后调用 defineClass0 根据字节码生成代理类。
  2. 我们可以看下动态代理的类图
  3. 在上图中$ProxyN是代理类。继承Proxy类。在实现了接口。$ProxyN其实跟User是没有关系的。调用是通过AInvocationHandler来实现的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值